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:
What's new?
OpenIddict now includes a client stack
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
OAuthHandler
methods.
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:
1 | services.AddOpenIddict() |
The following providers are already part of OpenIddict 4.0 preview1 and it's likely external contributions will introduce additional providers in future versions:
Provider name |
---|
Apple |
GitHub |
Microsoft |
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.
The token generation/validation pipeline got a massive overhaul
While this change should be invisible to most OpenIddict users, the ProcessAuthentication
and 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 GenerateToken(Context)
and 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.
The OpenIddict claims extensions were reworked
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 ClaimsPrincipal
and ClaimsIdentity
.
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 ClaimsIdentity
/ClaimsPrincipal
to set claim destinations of all claims in a single pass:
1 | principal.SetDestinations(static claim => claim.Type switch |
netcoreapp2.1
and net5.0
TFMs were removed
.NET Core 2.1 and .NET 5.0 are no longer supported by Microsoft so the OpenIddict 4.0 packages no longer target netcoreapp2.1
and 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).
Support for the iss
parameter was added to the OpenIddict server
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.
System.Text.Json.Nodes
is now fully supported on .NET >= 6.0
The OpenIddictParameter
primitive was updated to support JsonObject
, JsonArray
and 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:
1 | var properties = new AuthenticationProperties |
1 | { |
AuthenticationProperties.Items
is now preserved by the OpenIddict server and client stacks
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.
1 | var properties = _signInManager.ConfigureExternalAuthenticationProperties( |
Challenge handling in the server and validation stacks was improved
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.
What's next?
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 😁).