When I unveiled the OpenIddict 3.0 roadmap three years ago, I mentioned that having an OpenIddict client would be a very nice addition but that implementing it as part of 3.0 wasn't realistic. Today, I'm very happy to announce that the OpenIddict client will ship as part of OpenIddict's next major version.
Why a new client?
A few client libraries already exist for .NET, including:
- For ASP.NET Core, an OAuth 2.0 base handler developed by Microsoft that we massively use for the aspnet-contrib project (more than 80 OAuth 2.0 services are supported at the time of writing!)
- For ASP.NET Core, an OpenID Connect handler developed by Microsoft.
- For ASP.NET 4.x/OWIN, an OpenID Connect middleware maintained by Microsoft.
- For console and GUI applications, a certified OpenID Connect client developed by Duende Software.
- For Blazor WASM applications, an OpenID Connect integration based on the oidc-client-js library.
So why do we need another one? Am I reinventing the wheel by introducing another OIDC client stack?
Well, that's definitely a legit question. First, I have to say that these implementations work just fine and that I've used them happily other the years. Actually, I even contributed to some of these implementations multiple times so I have a fairly good experience working with them.
In a nutshell, here's what motivated me:
While all these libraries offer very specialized implementations, none of them offers a unified experience that allowing sharing a common code base usable on, say, ASP.NET Core and Blazor WASM applications: what you learned about the ASP.NET Core OIDC handler is not applicable to Blazor WASM, that uses a completely different OIDC client stack under the hood.
The OIDC integration for Blazor WASM uses oidc-client-js, that was archived in June 2021 and is no longer supported. While the Blazor OIDC wrapper itself is supported by Microsoft, the library it uses under the hood is not and won't receive any bug or security fix, which is a bit surprising to me, considering its author is still sponsored by Microsoft.
While it's supported by Microsoft, the Blazor OIDC wrapper doesn't actually get much love and suffers from annoying design issues that affect OpenIddict users that the team is unwilling to fix.
The OAuth 2.0 base handler for ASP.NET Core offers a straightforward API for creating derived OAuth 2.0 clients that we successfully used in the aspnet-contrib social providers. Unfortunately, its simplicity comes at a cost: it's not composable. Concretely, it means that every time we need to customize something (e.g adding a parameter to the token request), we end up duplicating more code than what we should (e.g to add a token request parameter, you also need to take care of sending the HTTP request and handling the response, which is something the OAuth 2.0 base handler does for you if you don't override the
OAuthHandler<T>.ExchangeCodeAsync(OAuthCodeExchangeContext context)
method).There's also another downside with the OAuth 2.0 base handler: it doesn't support OpenID Connect. Yet, we received contributions to add OAuth 2.0 providers that also support OpenID Connect: while ASP.NET Core has a dedicated OIDC handler that is more appropriate for these cases, many people like the simpler registration story the OAuth 2.0 base handler and the aspnet-contrib providers offer. Retrospectively, we shouldn't have accepted these contributions as these providers don't benefit from the additional security checks a real OpenID Connect implementation requires (e.g
nonce
,at_hash
orc_hash
validation, etc.)The OAuth 2.0 base handler doesn't support the OAuth 2.0 Authorization Server Metadata specification that backported the OpenID Connect server discovery feature to the OAuth 2.0 world and that allows finding the location of the authorization and token endpoints dynamically, without having to hardcode them. While the adoption is slow, I'd expect more and more services to support it in the next few years.