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

.NET5托管WebAssembly同时配置Azure AD与个人账号认证问题求助

问题1:externallogin页面404修复方案

问题原因与修复步骤:

  • 错误的默认挑战方案配置:你当前把DefaultChallengeScheme设为了OpenIdConnectDefaults.AuthenticationScheme,这会导致登录请求直接触发Azure AD OIDC挑战,跳过IdentityServer4的外部登录流程,回调后的路由和Identity默认的外部登录处理逻辑不匹配,触发404。
    修复:移除AddAuthentication的sharedOptions配置,改为默认配置即可:
// 替换原有带sharedOptions的AddAuthentication配置
services.AddAuthentication()
    .AddOpenIdConnect("AAD", "Azure Active Directory", options =>
    {
        options.ClientSecret = "<Secrete>";
        options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
        options.ClientId = "<ClientId>";
        options.Authority = "https://login.microsoftonline.com/<tenantId>/";
        // 建议改成自定义回调路径,避免和默认oidc回调冲突,需和Azure门户配置完全一致
        options.CallbackPath = "/signin-aad"; 
        options.SaveTokens = true;
        options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
    })
    .AddCookie()
    .AddIdentityServerJwt();

如果需要直接跳转AAD登录不需要展示登录方式选择页,可以在前端登录按钮的跳转地址中指定scheme参数:/Identity/Account/ExternalLogin?scheme=AAD&returnUrl=xxx即可。

  • 缺失Razor Pages路由映射:Identity的外部登录相关页面是基于Razor Pages实现的,Blazor WASM托管模板默认可能没有开启Razor Pages路由,需要在Configure方法的端点配置里添加映射:
app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages(); // 必须添加,负责Identity相关页面的路由解析
    endpoints.MapControllers();
    endpoints.MapBlazorHub();
    endpoints.MapFallbackToFile("index.html");
});

如果使用自定义Identity UI没有采用默认脚手架页面,需要确保你已经手动实现了/Identity/Account/ExternalLogin对应的页面处理逻辑,否则也会触发404。


问题2:自动创建Azure AD对应本地用户实现

在AddOpenIdConnect的配置里添加Events配置,处理OnTicketReceived事件,在这个事件中获取Azure AD返回的用户信息,查询本地数据库,不存在则自动创建用户:

.AddOpenIdConnect("AAD", "Azure Active Directory", options =>
{
    // 原有配置保持不变,新增Events配置
    options.Events = new OpenIdConnectEvents
    {
        OnTicketReceived = async context =>
        {
            // 从返回的Claims中获取Azure AD用户唯一标识,优先取oid
            var oid = context.Principal.FindFirstValue("oid") ?? context.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
            var userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>();
            
            // 查找本地是否存在关联的用户,可根据业务调整匹配字段
            var user = await userManager.FindByLoginAsync("AAD", oid);
            if (user == null)
            {
                // 从Claims中提取用户基础信息
                var email = context.Principal.FindFirstValue("preferred_username") ?? context.Principal.FindFirstValue(ClaimTypes.Email);
                var name = context.Principal.FindFirstValue("name") ?? email.Split('@')[0];
                
                // 创建本地用户
                user = new ApplicationUser
                {
                    UserName = email,
                    Email = email,
                    DisplayName = name, // 根据你的ApplicationUser自定义字段调整
                    EmailConfirmed = true // Azure AD返回的邮箱默认已验证,可直接设为true
                };
                var createResult = await userManager.CreateAsync(user);
                if (createResult.Succeeded)
                {
                    // 关联外部登录信息到本地用户
                    await userManager.AddLoginAsync(user, new UserLoginInfo("AAD", oid, "Azure Active Directory"));
                    // 如需默认分配角色可在此处添加
                    await userManager.AddToRoleAsync(user, "普通用户");
                }
                else
                {
                    // 处理创建失败逻辑
                    context.Fail("用户创建失败:" + string.Join(",", createResult.Errors.Select(e => e.Description)));
                    return;
                }
            }
            // 可选:将本地用户的角色信息添加到Claims中
            var roles = await userManager.GetRolesAsync(user);
            var appIdentity = new ClaimsIdentity(context.Principal.Identity);
            foreach (var role in roles)
            {
                appIdentity.AddClaim(new Claim(ClaimTypes.Role, role));
            }
            context.Principal = new ClaimsPrincipal(appIdentity);
        }
    };
});

注意事项:

确保Azure AD的应用注册中已经开放了profile、email、openid三个API权限,否则无法正常获取对应的用户Claims。测试时请清除浏览器缓存,避免旧Cookie影响登录流程。


内容的提问来源于stack exchange,提问作者Javad Esfandiari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:36:03