You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 00:12:17