Home > front end >  Blazor Server Side and Azure B2C Login using invite, how to authenticate with returned token?
Blazor Server Side and Azure B2C Login using invite, how to authenticate with returned token?

Time:12-01

I have followed a few different tutorials on how to get Signup by invite working and I am very close to getting it working in blazor server side but I am having issues with the final returned token.

I have 2 authentications setup, one which is the default Microsoft Identity and my custom one which is used for sign ups via an email link.

Everything seems to work until the final step. When you click the link, it takes you to Azure signup pages asking for Name, email etc and then it returns back to my site with the returned "id_token".

When this happens I get the following error.

InvalidOperationException: The authentication handler registered for scheme 'OpenIdConnect' is 'OpenIdConnectHandler' which cannot be used for SignInAsync. The registered sign-in schemes are: Cookies.

I set breakpoints in the OpenIdConnectEvents on event TicketReceived and I can see that the TicketReceivedContext object has a valid ClaimsPrinciple with correct claims and IsAuthenticated is true.

My return page never gets hit because of the error.

Any ideas on how to fix this?

Edit My startup registration for the 2 authentications.

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>{    

builder.Configuration.Bind("AzureAd", options);

options.ResponseType = OpenIdConnectResponseType.IdToken;

options.Events = new CustomOpenIdConnectEvents();
options.DataProtectionProvider = protector;

}, subscribeToOpenIdConnectMiddlewareDiagnosticsEvents: true);

and

string invite_policy = builder.Configuration.GetSection("AzureAdB2C")["SignUpSignInPolicyId"]; builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddOpenIdConnect(invite_policy, GetOpenIdSignUpOptions(invite_policy, builder.Configuration));

Action<OpenIdConnectOptions> GetOpenIdSignUpOptions(string policy, Microsoft.Extensions.Configuration.ConfigurationManager Configuration)
           => options =>
           {
               builder.Configuration.Bind("AzureAdB2C", options);

               options.ResponseType = OpenIdConnectResponseType.IdToken;

               string B2CDomain = Configuration.GetSection("AzureAdB2C")["B2CDomain"];
               string Domain = Configuration.GetSection("AzureAdB2C")["Domain"];

               options.MetadataAddress = $"https://{B2CDomain}/{Domain}/{policy}/v2.0/.well-known/openid-configuration";

               options.ResponseMode = OpenIdConnectResponseMode.FormPost;                                                                              

               options.CallbackPath = "/LoginRedirect";                        

               options.Events = new CustomOpenIdConnectEvents();

               options.DataProtectionProvider = protector;
           };

Update:
So thanks to Wolfspirit's answer I am now closer to solving the issue. My start up registration has now changed to this.

string invite_policy = builder.Configuration.GetSection("AzureAdB2C")["SignUpSignInPolicyId"];
builder.Services.AddAuthentication(options => {
options.DefaultScheme = 
CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddOpenIdConnect(invite_policy, GetOpenIdSignUpOptions(invite_policy, builder.Configuration))
.AddMicrosoftIdentityWebApp(options =>{    

builder.Configuration.Bind("AzureAd", options);

options.ResponseType = OpenIdConnectResponseType.IdToken;

options.Events = new CustomOpenIdConnectEvents();
options.DataProtectionProvider = protector;

}, subscribeToOpenIdConnectMiddlewareDiagnosticsEvents: true);

My issue now is that User.Identity.Name is returning a null if you login through the signup method. If you login the normal default way then everything is fine. I checked the claims and they are correct so not sure why Name is no being populated.

CodePudding user response:

According to the error you got, you've set "OpenIdConnect" as the SignIn scheme inside the "AddAuthentication" call. It would be helpful to know how you've set up your Program.cs/Startup.cs but it should look similar to this for example:

https://github.com/onelogin/openid-connect-dotnet-core-sample/blob/master/Startup.cs#L32

You need to use both schemes cause one manages the "where to store the authentication after login" while the other manages the "how to log in" way. If you set both to OpenIdConnect then you can log in but asp.net core will not know how to actually "sign" you in by storing the login result into a cookie.

CodePudding user response:

ok so I have figured out the answer, with credit to Wolfspirit for pointing me in the right direction.

string invite_policy = builder.Configuration.GetSection("AzureAdB2C")["SignUpSignInPolicyId"];
builder.Services.AddAuthentication(options => {
     options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
     options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddOpenIdConnect(invite_policy, GetOpenIdSignUpOptions(invite_policy, builder.Configuration))
.AddMicrosoftIdentityWebApp(options =>{    

builder.Configuration.Bind("AzureAd", options);

options.ResponseType = OpenIdConnectResponseType.IdToken;

options.Events = new CustomOpenIdConnectEvents();
options.DataProtectionProvider = protector;

// Thanks to Nan Yu for the folowing to fix the null name after login
//https://stackoverflow.com/questions/54444747/user-identity-name-is-null-after-federated-azure-ad-login-with-aspnetcore-2-2
options.TokenValidationParameters = new TokenValidationParameters() { NameClaimType = "name" };

}, subscribeToOpenIdConnectMiddlewareDiagnosticsEvents: true); // don't need this, for debugging.
  • Related