If you (like me) were hoping to “easily” create a Blazor application that connects to a generic OIDC identity-provider using the Microsoft.AspNetCore.Components.WebAssembly.Authentication
library, while also supporting connections to Azure Active Directory (AAD) this way, you’ll be disappointed.
The idea is simple, AAD does support OIDC and therefore now why shouldn’t a generic OIDC client be able to connect to AAD as well. Unfortunately the hurdles are more than you would like to overcome.
While the Microsoft.Authentication.WebAssembly.Msal
library for AAD is an extension of the underlying Microsoft.AspNetCore.Components.WebAssembly.Authentication
library, it does a lot more than just boilerplate configuration of the underlying generic OIDC.
The basic difference can be found, for example, in the “interop” part with the underlying oidc-client
JavaScript module.
AuthenticationService.ts
inMicrosoft.AspNetCore.Components.WebAssembly.Authentication
,AuthenticationService.ts
inMicrosoft.Authentication.WebAssembly.Msal
.
This is manifested for example when retrieving access-tokens. The MSAL version “fixes” the AAD specificity that when querying atoken
endpoint does not always return an access-token with all required scopes (the details are for a broader discussion, but e.g. you don’t get a token that hasUser.Read
scope in it along with the custom-scope of your API, etc.).
The base library uses the “caching” of tokens in the oidc-client
UserManager and relies on the assumption “If token-endpoint returned an access-token, then that token has all the required scopes in it.” (i.e., it stores the required scopes for the retrieved token, and then returns the already retrieved token the next time the same scopes are requested).
The “fixed” MSAL library knows this shortcoming of the underlying oidc-client and knows that while it claims to have a token for some set of scopes, the access-token may not actually have those scopes. Therefore, it “turns off” caching at this level and always gets the token again.