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

如何通过OpenIdConnect集成Asp.Net Identity与Azure AD授权并实现切换?

当然可以实现!你完全可以在ASP.NET Core中同时集成Identity本地授权和Azure AD的OpenID Connect授权,下面我会一步步帮你调整现有配置,让两种方式都能正常工作且支持自由切换。

步骤1:添加ASP.NET Core Identity服务

首先,你需要在ConfigureServices方法中注册Identity服务——这是开启本地账号密码授权的基础。如果你用Entity Framework Core做数据存储,代码大致如下:

// 添加Identity服务(如果用自定义用户/角色类型,替换成你自己的类型即可)
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

注意:AddDefaultIdentity会自动注册Cookie认证,使用的方案是IdentityConstants.ApplicationScheme,我们后续的认证配置需要兼容这个设定。

步骤2:调整认证配置

你现有的Azure AD OIDC配置大部分是正确的,但我们需要更新认证选项,让它同时支持两种授权方案,并且不要把默认挑战方案固定为Azure AD(这样用户才能自主选择登录方式)。修改后的配置如下:

_services.AddAuthentication(options =>
{
    // 将默认认证方案设为Cookie认证(同时兼容Identity本地登录和Azure AD登录)
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    // 不要设置默认挑战方案——让用户自主选择用哪种方式登录
    // options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
// 保留你原有的Azure AD OIDC配置,但确保SignInScheme使用Cookie方案
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.ClientId = clientId;
    options.ClientSecret = clientSecret;
    options.Authority = $"{baseAuthorityUrl}/{tenantId}/v2.0";
    options.CallbackPath = new PathString(callBackPath);
    options.Scope.Add("email");
    options.Scope.Add("profile");
    options.ResponseType = "code id_token";
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;
    options.TokenValidationParameters = new TokenValidationParameters
    {
        NameClaimType = "name"
    };

    // 可选功能:将Azure AD用户关联到本地Identity账号(如果不存在则自动创建)
    options.Events = new OpenIdConnectEvents
    {
        OnTokenValidated = async context =>
        {
            var email = context.Principal.FindFirstValue(ClaimTypes.Email);
            if (!string.IsNullOrEmpty(email))
            {
                var userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<IdentityUser>>();
                var user = await userManager.FindByEmailAsync(email);
                if (user == null)
                {
                    // 创建一个与Azure AD账号绑定的本地用户
                    user = new IdentityUser { UserName = email, Email = email };
                    await userManager.CreateAsync(user);
                }
                // 让本地Identity账号也完成登录,保持身份一致性
                await context.HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, 
                    await userManager.CreateUserPrincipalAsync(user));
            }
            await Task.CompletedTask;
        }
    };
})
// 显式添加Cookie认证方案(虽然Identity可能已经自动添加,但这样配置更清晰)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme);
步骤3:更新登录UI,提供两种登录选项

你需要修改登录页面(如果用Identity脚手架生成的话,通常是Login.cshtml),添加Azure AD登录的入口。

首先,在AccountController中添加一个触发Azure AD认证挑战的Action:

public IActionResult LoginWithAzureAd(string returnUrl = null)
{
    var redirectUrl = Url.Action("Index", "Home", new { returnUrl });
    return Challenge(
        new AuthenticationProperties { RedirectUri = redirectUrl },
        OpenIdConnectDefaults.AuthenticationScheme);
}

然后在Login.cshtml中添加Azure AD登录的按钮/表单,和本地登录表单并列:

<div class="row">
    <div class="col-md-4">
        <section>
            <h4>本地账号登录</h4>
            <hr />
            <!-- 这里保留你原有的本地登录表单 -->
        </section>
    </div>
    <div class="col-md-4">
        <section>
            <h4>使用Azure AD登录</h4>
            <hr />
            <form asp-action="LoginWithAzureAd" asp-route-returnUrl="@Model.ReturnUrl" method="post">
                <button type="submit" class="btn btn-primary">使用Azure AD登录</button>
            </form>
        </section>
    </div>
</div>
步骤4:验证两种授权方式的兼容性

[Authorize]特性会对两种方式登录的用户生效,因为它们都使用了默认的Cookie认证方案。如果你需要限制某个页面只能用特定方式登录,可以指定认证方案:

// 仅允许Azure AD登录的用户访问
[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)]
public IActionResult AzureAdOnlyPage()
{
    return View();
}

// 仅允许本地Identity账号登录的用户访问
[Authorize(AuthenticationSchemes = IdentityConstants.ApplicationScheme)]
public IActionResult LocalOnlyPage()
{
    return View();
}
排查小技巧
  • 如果你还没有生成过Identity的UI页面,可以运行dotnet aspnet-codegenerator identity命令来生成本地登录所需的表单和页面。
  • 检查Azure AD应用注册中的重定向URI,确保和你配置的CallbackPath完全一致。
  • 如果遇到Cookie相关问题,确保Cookie名称保持一致(或者让默认配置自动处理即可)。

内容的提问来源于stack exchange,提问作者Kipup fs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:56:43