I've got a Blazor .NET 8 Server app. It is using B2C for authentication and is behind an application gateway.
After successful login, some users are getting redirected to the redirect url:
The app gets stuck here and users are presented with correlation error:
correlation_error
If user updates the url and removes signin-oidc
so they are now just going to they are successfully logged in to the home page.
My B2C is configured like this:
"AzureAdB2C": {
"Instance": ";,
"ClientId": "",
"Domain": "my-b2c.onmicrosoft",
"ObjectId": "",
"TenantId": "",
"ClientSecret": "",
"CallbackPath": "/signin-oidc",
"SignUpSignInPolicyId": "B2C_1_MyB2C_SignIn",
"SignedOutCallbackPath": "/signout",
}
B2C is configured with as a redirect url.
The strange thing is that this does not happen for every user at every login.
-- Update --
Adding more information via screenshots:
Here is the url sent for B2C login:
b2c-url
Here is my B2C App Registration Authentication:
b2c-redirects
Since my app is using a custom domain configured in my Application Gateway, I've coded my startup to set the redirect url if it is set in Environment Variables/appsettings:
if (!string.IsNullOrEmpty(builder.Configuration.GetValue<string>($"{authType}:CustomRedirectBaseUrl")))
{
var redirectUrlBase = builder.Configuration.GetValue<string>($"{authType}:CustomRedirectBaseUrl");
var redirectUrl = redirectUrlBase + builder.Configuration.GetValue<string>($"{authType}:CallbackPath");
logger.LogInformation($"Custom redirect url is found: {redirectUrl}");
builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, opts =>
{
opts.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = async context =>
{
logger.LogInformation($"OnRedirectToIdentityProvider: RedirectUri set to '{redirectUrl}'");
context.ProtocolMessage.RedirectUri = redirectUrl;
await Task.Yield();
},
OnRedirectToIdentityProviderForSignOut = async context =>
{
logger.LogInformation($"OnRedirectToIdentityProviderForSignOut: PostLogoutRedirectUri set to '{redirectUrlBase}'");
context.ProtocolMessage.PostLogoutRedirectUri = redirectUrlBase;
await Task.Yield();
}
};
});
}
My redirect url in Environment Variables (Azure Web App): env-variables
Here are my logs showing the system is setting the redirect url: logs
I've got a Blazor .NET 8 Server app. It is using B2C for authentication and is behind an application gateway.
After successful login, some users are getting redirected to the redirect url: https://example/signin-oidc
The app gets stuck here and users are presented with correlation error:
correlation_error
If user updates the url and removes signin-oidc
so they are now just going to https://example
they are successfully logged in to the home page.
My B2C is configured like this:
"AzureAdB2C": {
"Instance": "https://my-b2c.b2clogin",
"ClientId": "",
"Domain": "my-b2c.onmicrosoft",
"ObjectId": "",
"TenantId": "",
"ClientSecret": "",
"CallbackPath": "/signin-oidc",
"SignUpSignInPolicyId": "B2C_1_MyB2C_SignIn",
"SignedOutCallbackPath": "/signout",
}
B2C is configured with https://example/signin-oidc
as a redirect url.
The strange thing is that this does not happen for every user at every login.
-- Update --
Adding more information via screenshots:
Here is the url sent for B2C login:
b2c-url
Here is my B2C App Registration Authentication:
b2c-redirects
Since my app is using a custom domain configured in my Application Gateway, I've coded my startup to set the redirect url if it is set in Environment Variables/appsettings:
if (!string.IsNullOrEmpty(builder.Configuration.GetValue<string>($"{authType}:CustomRedirectBaseUrl")))
{
var redirectUrlBase = builder.Configuration.GetValue<string>($"{authType}:CustomRedirectBaseUrl");
var redirectUrl = redirectUrlBase + builder.Configuration.GetValue<string>($"{authType}:CallbackPath");
logger.LogInformation($"Custom redirect url is found: {redirectUrl}");
builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, opts =>
{
opts.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = async context =>
{
logger.LogInformation($"OnRedirectToIdentityProvider: RedirectUri set to '{redirectUrl}'");
context.ProtocolMessage.RedirectUri = redirectUrl;
await Task.Yield();
},
OnRedirectToIdentityProviderForSignOut = async context =>
{
logger.LogInformation($"OnRedirectToIdentityProviderForSignOut: PostLogoutRedirectUri set to '{redirectUrlBase}'");
context.ProtocolMessage.PostLogoutRedirectUri = redirectUrlBase;
await Task.Yield();
}
};
});
}
My redirect url in Environment Variables (Azure Web App): env-variables
Here are my logs showing the system is setting the redirect url: logs
Share edited Mar 4 at 18:43 user29875125 asked Mar 3 at 20:43 user29875125user29875125 12 bronze badges 2 |2 Answers
Reset to default 0I created a sample Blazor server (.NET 8) application and successfully authenticated using Azure AD B2C.
Please refer this blog for creating the application and configuring Azure B2C authentication.
Make sure you're defining the correct policy name, domain, or instance in your appsettings.json
.
appsettings.json:
{
"AzureAdB2C": {
"Instance": "https://{ Azure B2C Domain Name}.b2clogin/tfp/",
"ClientId": "<Client-Id>",
"CallbackPath": "/signin-oidc",
"Domain": "{ Azure B2C Domain Name}.onmicrosoft",
"SignUpSignInPolicyId": "B2C_1_Blazorsigninsingup",
"ResetPasswordPolicyId": "",
"EditProfilePolicyId": ""
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
My program.cs file:
using blazorb2c.Components;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Identity.Web.UI;
using Microsoft.Identity.Web;
using System.Reflection;
using System.Security.Claims;
using System.Linq.Dynamic.Core;
using blazorb2c.Components;
namespace BlazorAzureB2C
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
var env = builder.Environment;
builder.Configuration.AddJsonFile($"appsettings{env.EnvironmentName}.json", optional: true);
builder.Configuration.AddEnvironmentVariables()
.AddUserSecrets(Assembly.GetExecutingAssembly(), true);
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddMicrosoftIdentityConsentHandler();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddHttpClient();
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<HttpContextAccessor>();
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
builder.Configuration.Bind("AzureAdB2C", options);
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = async ctxt =>
{
await Task.Yield();
},
OnAuthenticationFailed = async ctxt =>
{
await Task.Yield();
},
OnSignedOutCallbackRedirect = async ctxt =>
{
ctxt.HttpContext.Response.Redirect(ctxt.Options.SignedOutRedirectUri);
ctxt.HandleResponse();
await Task.Yield();
},
OnTicketReceived = async ctxt =>
{
if (ctxt.Principal != null)
{
if (ctxt.Principal.Identity is ClaimsIdentity identity)
{
var colClaims = await ctxt.Principal.Claims.ToDynamicListAsync();
var IdentityProvider = colClaims.FirstOrDefault(
c => c.Type == "http://schemas.microsoft/identity/claims/identityprovider")?.Value;
var Objectidentifier = colClaims.FirstOrDefault(
c => c.Type == "http://schemas.xmlsoap./ws/2005/05/identity/claims/nameidentifier")?.Value;
var EmailAddress = colClaims.FirstOrDefault(
c => c.Type == "http://schemas.xmlsoap./ws/2005/05/identity/claims/emailaddress")?.Value;
var FirstName = colClaims.FirstOrDefault(
c => c.Type == "http://schemas.xmlsoap./ws/2005/05/identity/claims/givenname")?.Value;
var LastName = colClaims.FirstOrDefault(
c => c.Type == "http://schemas.xmlsoap./ws/2005/05/identity/claims/surname")?.Value;
var AzureB2CFlow = colClaims.FirstOrDefault(
c => c.Type == "http://schemas.microsoft/claims/authnclassreference")?.Value;
var auth_time = colClaims.FirstOrDefault(
c => c.Type == "auth_time")?.Value;
var DisplayName = colClaims.FirstOrDefault(
c => c.Type == "name")?.Value;
var idp_access_token = colClaims.FirstOrDefault(
c => c.Type == "idp_access_token")?.Value;
}
}
await Task.Yield();
},
};
});
builder.Services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.UseAntifery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
}
}
}
Add the correct Redirect URI to your Azure B2C app registration as shown below.
I've successfully authenticated to Azure B2C.
I ended up getting a working solution:
Added middleware to intercept requests to
/signin-oidc
and/MicrosoftIdentity/Account/Error
and redirect back to home pageAdded empty razor page with path of /
signin-oidc
and/MicrosoftIdentity/Account/Error
My home page auto redirects to /MicrosoftIdentity/Account/SignIn
if the user is not authenticated.
Any of the requests coming to /signin-oidc
are not registered as authenticated, the home page re directs them to b2c login, and they are quickly returned to the home page and logged in.
Good user path:
Navigate to
https://www.example
User not authenticated and auto-redirected to b2c login
- Enter Credentials & 2FA
Redirected and logged into
https://www.example
Troublesome user path:
Navigate to
https://www.example
Auto-redirected to b2c login
- Enter Credentials & 2FA
Redirected and not logged into
https://www.example/signin-oidc
Middleware redirects to
https://www.example
User not authenticated and auto-redirected to b2c login
- No inputs are required here
Redirected and logged into
https://www.example
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745073096a4609671.html
The strange thing is that this does not happen for every user at every login.
--> so that the error records in the screenshot occurred intermittently? It so, then I'm afraid it's more likely a network issue or something else but not code issue.... – Tiny Wang Commented Mar 4 at 10:24