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

整合OpenIdConnect与ASP.NET Identity时如何避免无限重定向循环

登录系统引入ASP.NET Identity后AD认证无限重定向问题

我正在开发一个支持**组织邮箱(AD认证)**和普通邮箱密码登录的系统,系统登录界面提供两个选项供用户选择登录方式。

添加ASP.NET Identity前,AD认证的登录/登出功能正常,实现代码如下:

添加Identity前的工作代码

Program.cs

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(config.GetRequiredSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(
     ["user.read"]
)
.AddInMemoryTokenCaches();

builder.Services.Configure<OpenIdConnectOptions>(
    OpenIdConnectDefaults.AuthenticationScheme,
    options =>
    {
        options.SignedOutCallbackPath = "/signout-callback-oidc";
        options.SignedOutRedirectUri = "/Identity/Account/SignOut";
    }
);

AccountController.cs

[Route("SignIn")]
[Route("[area]/[controller]/[action]")]
public IActionResult SignIn()
{
    var redirect = Url.Action("Overview", "DashboardView", new { area = "Events" });

    var scheme = OpenIdConnectDefaults.AuthenticationScheme;

    return Challenge(
        new AuthenticationProperties { RedirectUri = redirect },
        scheme
    );
}

[Route("SignOut")]
[Route("[area]/[controller]/[action]")]
public new IActionResult SignOut()
{
    var callbackUrl = Url.Action("LogIn", "Account", new { area = "Identity" }, protocol: Request.Scheme);

    return SignOut(new AuthenticationProperties { RedirectUri = callbackUrl },
        CookieAuthenticationDefaults.AuthenticationScheme,
        OpenIdConnectDefaults.AuthenticationScheme);
}

引入ASP.NET Identity后的问题

添加Identity后,代码更新如下,但出现无限重定向至SignIn方法的问题,导致用户无法通过Entra Authentication登录:

问题代码(Program.cs)

builder.Services.AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<ActraContext>()
    .AddDefaultTokenProviders();

// Updated AddAuthentication for Identity
builder.Services.AddAuthentication(options => {
        options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
        options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddMicrosoftIdentityWebApp(config.GetRequiredSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi(
        ["user.read"]
    )
    .AddInMemoryTokenCaches();

builder.Services.ConfigureApplicationCookie(options => {
    options.LoginPath = "/Identity/Account/SignIn";
    options.LogoutPath = "/Identity/Account/SignOut";
    options.AccessDeniedPath = "";
    options.ReturnUrlParameter = "returnUrl";
});

目前尚未开发邮箱密码认证部分,已参考官方文档。

问题原因及修复方案

核心原因

引入Identity后,DefaultAuthenticateScheme设为IdentityConstants.ApplicationScheme(Identity的Cookie方案),但AD认证成功后,系统无法将OIDC认证的用户转换为Identity用户,导致后续请求仍被判定为未认证,触发LoginPath的重定向,形成循环。

修复步骤

  1. 配置OIDC回调后的用户同步逻辑
    在OIDC选项中添加OnTokenValidated事件,将AD用户同步到Identity系统(创建或更新用户),并替换为Identity的ClaimsPrincipal:

    builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
    {
        options.SignedOutCallbackPath = "/signout-callback-oidc";
        options.SignedOutRedirectUri = "/Identity/Account/SignOut";
    
        options.Events.OnTokenValidated = async context =>
        {
            var userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<IdentityUser>>();
            var email = context.Principal.FindFirstValue(ClaimTypes.Email);
            
            if (string.IsNullOrEmpty(email))
            {
                context.Fail("Email claim not found");
                return;
            }
    
            var user = await userManager.FindByEmailAsync(email);
            if (user == null)
            {
                user = new IdentityUser { UserName = email, Email = email };
                var result = await userManager.CreateAsync(user);
                if (!result.Succeeded)
                {
                    context.Fail("Failed to create user");
                    return;
                }
            }
    
            var identityPrincipal = await userManager.CreateUserPrincipalAsync(user);
            context.Principal = identityPrincipal;
        };
    });
    
  2. 调整SignIn方法逻辑
    保留明确指定挑战方案为OIDC,同时支持传入returnUrl参数:

    [Route("SignIn")]
    [Route("[area]/[controller]/[action]")]
    public IActionResult SignIn(string returnUrl = null)
    {
        var redirectUrl = returnUrl ?? Url.Action("Overview", "DashboardView", new { area = "Events" });
        return Challenge(new AuthenticationProperties { RedirectUri = redirectUrl }, OpenIdConnectDefaults.AuthenticationScheme);
    }
    
  3. 修正Logout逻辑
    登出时需同时清除Identity Cookie和OIDC会话,将原CookieAuthenticationDefaults.AuthenticationScheme替换为IdentityConstants.ApplicationScheme:

    [Route("SignOut")]
    [Route("[area]/[controller]/[action]")]
    public new IActionResult SignOut()
    {
        var callbackUrl = Url.Action("SignIn", "Account", new { area = "Identity" }, protocol: Request.Scheme);
        return SignOut(
            new AuthenticationProperties { RedirectUri = callbackUrl },
            IdentityConstants.ApplicationScheme,
            OpenIdConnectDefaults.AuthenticationScheme);
    }
    
  4. 确认中间件顺序
    Program.cs中中间件顺序必须遵循认证在前、授权在后:

    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapControllers();
    

内容的提问来源于stack exchange,提问作者Diego Salas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 02:41:05