I am trying to set up SSO with a Blazor WebAssmebly app (.NET 7).
On the Azure AD side of things, I have registered an application (SPA) with a login callback URI of https://localhost/authentication/login-callback
.
I have disabled implicit and hybrid flows (unchecked Access and ID tokens). No other configuration of note.
On the app side of thigs, I have the following section in appsettings.json:
"AuthSettings": {
"Authority": "https://login.microsoftonline.com/common/",
"ClientId": "<my client id>",
"ResponseType": "code"
}
In Program.cs:
builder.Services.AddOidcAuthentication(options =>
{
// Configure your authentication provider options here.
// For more information, see https://aka.ms/blazor-standalone-auth
builder.Configuration.Bind("AuthSettings", options.ProviderOptions);
});
index.html has the
<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>
line as well.
In general the setup is the standard one that comes with the Blazor WebAssembly VS project template when the Individual Accounts authentication type is selected.
When I log in with my Microsoft account, I get redirected to /authentication/login-callback
, with a code
, a state
, and a session_state
. I get a 200 response. A POST request is then sent to https://login.microsoftonline.com/common/oauth2/token
with the code and other data, and I get an access, a refresh, and an ID token. So far so good.
Problem is, the frontend shows this:
There was an error trying to log you in: 'There was an error signing in.'
and I have no idea why. Everything seems to have worked perfectly so far.
I tried looking into the JS source for this message, and it looks like this function is the source, in AuthenticationService.js:
async completeSignIn(t) {
this.trace("completeSignIn", t);
const e = await this.loginRequired(t)
, r = await this.stateExists(t);
try {
const e = await this._userManager.signinCallback(t);
return window.self !== window.top ? this.operationCompleted() : (this.trace("completeSignIn-result", e),
this.success(e && e.state))
} catch (t) {
return e || window.self !== window.top || !r ? this.operationCompleted() : this.error("There was an error signing in.")
}
}
but I have no idea how to debug this. I enabled trace logs in the console, but it just records the GET request to login-callback
.
Any help please? Is it a configuration issue, or a bug? and how can I go about debugging it? I tried enabling debugging via the Chrome developer tools, but that’s just another rabbit hole of issues.
Has anyone been able to set up OIDC authentication with Microsoft accounts in Blazor WebAssembly?
PS. I also tried MSAL, but that led into even more issues (e.g. popup windows that didn’t close, etc. etc.). I tried Google OIDC as well, but, you guessed it, more issues — I even raised another question in SO about that.
All in all, I’m quite a bit disappointed with the state of Blazor authentication right now. I haven’t been able to make this simple thing work for several days now. It’s a basic, straightforward feature that most developers are going to need at some point, and honestly I would have expected this to work out of the box.
==============================================================
UPDATE:
I tried @Harshitha ‘s suggestion to set up MSAL via Visual Studio. Indeed, the experience was much smoother, by going to Connected Services and adding Microsoft identity platform.
It even worked once or twice, logging both my tenant user and my personal account!
BUT
after a couple of tries, I was faced with this:
i.e. after logging in, the popup is not closed, and the app is frozen. If I close the popup via the X button, I cannot click anything in my app window.
Looks like a javascript issue?
I can consistently reproduce it by logging in, logging out, and logging back in. The second login freezes as above.
EDIT: Interestingly, I could only reproduce the above while running the app with Debugging enabled (F5
). I have made no changes to the original launchSettings.json
2
Answers
I have tried to configure Authentication with
Microsoft Identity Platform
for a .NET 8 PreviewBlazor WASM
.Check the below steps.
Microsoft Identity Platform
Authentication Type .Connected Services
, add theMicrosoft Identity platform
Service dependency.My
appsettings.json
:Output:
I think your code is fine. Looks like your fundamental problem may be related to the ID token validation that occurs before your app’s library accepts received tokens. You may need to configure values such as an expected issuer.
Start by looking more closely at the ID token in a JWT viewer and understand its contents. See if there is a
nonce
field in the JWT header. If so then add an API scope to the OAuth client registration. Steps 3 and 6 of my blog post provide further details.