Blazor集成AAD与Azure B2C双认证的登录路径配置问题
多认证方案登录跳转实现方案
不用找B2C对应的内置MicrosoftIdentityUI登录路径——AddMicrosoftIdentityUI提供的MicrosoftIdentity/Account/SignIn端点默认只会触发默认认证方案(也就是你配置的Azure AD)的Challenge流程,本身没有给自定义Scheme预留入口,找不到是正常的。
你要把逻辑封装在公共类库、避免每个消费项目单独写控制器,按下面两步做就行:
1. 修正认证配置的细节问题
首先改两个配置错误,避免后续踩坑:
- 你B2C认证配置里的
options.SignInScheme填错了,这个属性要指定登录成功后票据写入的Cookie方案,不是B2C的OIDC方案本身,改成Constants.B2CCookieScheme。 - 你重复调用了两次
AddControllersWithViews().AddMicrosoftIdentityUI(),只需要保留一次就行,重复注册服务没有意义。 - 之前找不到Cookie的
LoginPath配置入口,是因为AddMicrosoftIdentityWebApp把OIDC逻辑和Cookie逻辑拆分注册了,你只需要单独给B2C对应的Cookie方案配置选项就行,示例代码:
// 放在B2C认证服务注册代码之后即可 services.Configure<CookieAuthenticationOptions>(Constants.B2CCookieScheme, options => { options.LoginPath = "/Account/B2CSignIn"; options.LogoutPath = "/Account/B2CSignOut"; });
2. 在公共类库中内置通用登录端点
不用让每个消费项目自己写带[Authorize]特性的控制器,直接在公共类库里封装最小API端点,所有引用类库的项目只需要加一行路由映射代码就能用。
在公共类库中新增静态扩展类:
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; public static class SharedAuthEndpointExtensions { public static IEndpointRouteBuilder MapSharedAuthEndpoints(this IEndpointRouteBuilder endpoints) { // Azure AD 登录端点 endpoints.MapGet("/Account/ADSignIn", async (HttpContext context, string? returnUrl = "/") => { // 直接触发AD方案的认证挑战,自动跳转到AD登录页 await context.ChallengeAsync( OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties { RedirectUri = returnUrl }); }); // Azure B2C 登录端点 endpoints.MapGet("/Account/B2CSignIn", async (HttpContext context, string? returnUrl = "/") => { // 触发B2C方案的认证挑战,自动跳转到B2C登录页 await context.ChallengeAsync( Constants.B2CAuthenticationScheme, new AuthenticationProperties { RedirectUri = returnUrl }); }); // 可选:统一登出端点,自动识别当前登录方案执行登出 endpoints.MapGet("/Account/SignOut", async (HttpContext context) => { var authType = context.User.Identity?.AuthenticationType; if (authType == Constants.B2CAuthenticationScheme) { await context.SignOutAsync(Constants.B2CAuthenticationScheme); await context.SignOutAsync(Constants.B2CCookieScheme); } else { await context.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme); await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); } context.Response.Redirect("/"); }); return endpoints; } }
消费项目只需要在Program.cs的路由配置段,加一行app.MapSharedAuthEndpoints();即可,不需要写任何额外控制器。
页面使用方式
页面上的两个登录按钮直接配置跳转路径就行:
- 「使用AD登录」按钮跳转地址填
/Account/ADSignIn?returnUrl=@Context.Request.Path,如果要兼容你之前用的MicrosoftIdentity/Account/SignIn路径,把上面AD端点的路由模板改成这个地址就行,原有逻辑不用改。 - 「使用B2C登录」按钮跳转地址填
/Account/B2CSignIn?returnUrl=@Context.Request.Path,点击后会自动跳转至B2C登录流程,和你之前写专用控制器的效果完全一致。
如果不想让消费项目手动调用MapSharedAuthEndpoints,可以在公共类库里加一个启动过滤器自动注册路由,不过从维护成本来说,加一行映射代码已经足够简单,没必要做太复杂的自动注册逻辑。
内容的提问来源于stack exchange,提问作者Markus
相关产品推荐
相关产品推荐

