Earlier today, the first OpenIddict 4.0 preview was pushed to NuGet.org 🎉
As always, all the changes can be found on GitHub but here's a recap of the most interesting ones:
The introduction of a client stack in 4.0 is by far the most exciting change (well, at least for me 😁).
If you missed my previous post, I'd suggest reading it first as it details the motivation for creating it and the differences with existing offers like the ASP.NET Core OpenID Connect or OAuth 2.0 handlers.
The OpenIddict client will come with a companion package to simplify well-known Web services integrations
I had mentioned in my previous blog post that I was interested in developing an alternative to the aspnet-contrib providers that would be based on the new OpenIddict client instead of the ASP.NET Core 2.0 base handler and would have the following advantages:
Thanks to its dual-protocol nature, the OpenIddict client could enforce all the security checks introduced by OpenID Connect that a simple OAuth 2.0 client implementation like the ASP.NET Core OAuth 2.0 base handler wouldn't support, which means we could easily support both OAuth 2.0 and OpenID Connect providers without sacrificing security.
By being natively compatible with ASP.NET Core (from 2.1 to 7.0) and OWIN/Katana 4.2, the providers built on top of the OpenIddict client could be used in both recent ASP.NET Core apps and legacy ASP.NET >= 4.6.1 apps, making them usable in many more applications than the aspnet-contrib providers, that always target the most recent ASP.NET Core version.
Unlike the OAuth 2.0 base handler developed by Microsoft, the OpenIddict client comes with a composable events model that could allow eliminating code that we needed to copy in the aspnet-contrib providers when overriding certain
The good news is that this idea materialized as a dedicated
OpenIddict.Client.WebIntegration package that depends on
OpenIddict.Client and includes the logic necessary to deal with all the non-standard aspects of each supported provider. Unlike the aspnet-contrib providers,
OpenIddict.Client.WebIntegration relies on Roslyn Source Generators to dynamically create all the plumbing code, which makes it much easier to maintain. If you're interested in learning more about the technical details, don't miss the PR that introduced it.
If you're already familiar with the aspnet-contrib providers, migrating to the OpenIddict-based providers shouldn't be too complicated:
The following providers are already part of OpenIddict 4.0 preview1 and it's likely external contributions will introduce additional providers in future versions:
For more information about the differences between the aspnet-contrib providers and the OpenIddict-based providers, read Introducing the OpenIddict-powered providers
If you're interested in seeing a specific provider supported, please open a ticket on GitHub.
The OpenIddict client and the Web integration companion package will be compatible with the following .NET environments:
|Web framework version||.NET runtime version|
|ASP.NET Core 2.1||.NET Framework 4.6.1|
|ASP.NET Core 2.1||.NET Framework 4.7.2|
|ASP.NET Core 2.1||.NET Framework 4.8|
|ASP.NET Core 3.1||.NET Core 3.1|
|ASP.NET Core 6.0||.NET 6.0|
|ASP.NET Core 7.0||.NET 7.0|
|Microsoft.Owin 4.2||.NET Framework 4.6.1|
|Microsoft.Owin 4.2||.NET Framework 4.7.2|
|Microsoft.Owin 4.2||.NET Framework 4.8|
At this stage, it's still unclear whether support for Blazor will be part of 4.0 RTM as discussions around Blazor's authentication stack are still pending. I hope I'll hear from the ASP.NET team in the near future.
While this change should be invisible to most OpenIddict users, the
ProcessSignIn events were revamped in 4.0 to be much more flexible and give advanced users more control over the token generation and validation processes.
As part of this change, two new "sub-events" named
ValidateToken(Context) were introduced to enable the following scenarios:
- The token format (JWT or ASP.NET Core Data Protection) can now be controlled dynamically.
- Whether the token will have a corresponding entry in the database can now be controlled dynamically.
- Whether the token will be a reference token can now be controlled dynamically.
In previous versions, OpenIddict offered various extensions for
ClaimsPrincipal but not for
ClaimsIdentity, which made working with the latter (common with the OWIN integration, where
AuthenticationTicket.Identity is a
ClaimsIdentity) quite cumbersome. To fix that, many new extensions and overloads have been introduced for both
As part of this change, the
AddClaim overloads taking a list of claim destinations have been removed as overloads taking
params string parameters were too hard to version. Instead, users are encouraged to use the new
SetDestinations() overload on
ClaimsPrincipal to set claim destinations of all claims in a single pass:
principal.SetDestinations(static claim => claim.Type switch
.NET Core 2.1 and .NET 5.0 are no longer supported by Microsoft so the OpenIddict 4.0 packages no longer target
net5.0. While OpenIddict 4.0 can still be used on .NET Core 2.1 and .NET 5.0 thanks to its .NET Standard 2.0 TFM, users are encouraged to migrate to a supported .NET version to ensure they can receive security fixes.
OpenIddict 4.0 – client, server and validation – will still be fully compatible with ASP.NET Core 2.1 on .NET Framework 4.6.1 and higher (that has the same support lifecycle as ASP.NET 4.x applications).
Standardized in March 2022, the
iss authorization response parameter was introduced by RFC9207 as a way for OAuth 2.0 (and OpenID Connect) clients that support multiple providers to mitigate mix-up attacks. Since it's an important security measure, native
iss support was added to the OpenIddict server and client stacks.
OpenIddictParameter primitive was updated to support
JsonValue on .NET >= 6.0 (the lower-level
JsonElement struct is already supported by OpenIddict 3.0 on all .NET platforms).
You can also use these types via
AuthenticationProperties to return custom parameters from the OpenIddict endpoints. E.g:
var properties = new AuthenticationProperties
In 4.0, the authentication properties are now preserved by the ASP.NET Core and OWIN hosts in a special claim in all tokens (except access and identity tokens), which was required by the new client stack to flow certain properties set by Identity (e.g the selected external identity provider or a XSRF value bound to the user when associating an external provider to an existing ASP.NET Core Identity account). For consistency, the server stack was updated to offer the same feature.
var properties = _signInManager.ConfigureExternalAuthenticationProperties(
Last but not least, the way authentication challenges are handled by the OpenIddict server and validation services has been massively improved to be more consistent, standard-compliant and work around annoying issues caused by some OWIN or ASP.NET 4.x components (like the cookies middleware or the FormsAuthentication module) that are known to rewrite 401 responses to 302 redirects even if the response was already fully handled by OpenIddict.
With 4.0, Katana applications using the cookies middleware with the automatic mode enabled (the default value) or ASP.NET 4.x applications still using
FormsAuthenticationModule should no longer require any workaround for their 401 responses to work properly, making the user experience as good as with ASP.NET Core.
OpenIddict 4.0 preview1 will be the first release to include the new client stack, so it's likely improvements will be made based on the collected feedback. I also plan to include logout support in a future preview. Oh and hopefully, external contributions should also introduce additional providers in the Web integration companion package (at least, I hope so 😁).