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

ASP.NET Core中如何复用OIDC认证处理器配置与逻辑刷新令牌?

关于OIDC令牌刷新后是否需重新执行认证流程的问题

背景配置

当前使用的ASP.NET Core认证配置如下,框架会自动处理令牌验证、发现端点读取、公钥获取、声明映射等操作:

builder.Services
    .AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
    {
        // ...
    })
    .AddOpenIdConnect(options =>
    {
        // OIDC configurations
    });

自定义令牌刷新中间件

为实现令牌即将过期时自动刷新,编写了如下中间件,但获取新令牌后不确定是否需要复用OIDC登录时的处理逻辑:

app.Use(async (ctx, next) =>
{
    if (ctx.User.Identity!.IsAuthenticated)
    {
        var epoch = DateTimeOffset.MinValue.Ticks;
        long.TryParse(ctx.User.FindFirstValue(JwtRegisteredClaimNames.Exp), out epoch);
        var expireTime = DateTimeOffset.FromUnixTimeSeconds(epoch);

        if (expireTime < DateTimeOffset.UtcNow.AddMinutes(2))
        {
            var tokenManagementService = ctx.RequestServices.GetRequiredService<TokenManagementService>();
            var refreshResult = await tokenManagementService.RefreshTokenAsync(ctx);

            if (refreshResult is RefreshTokenFailure { LogoutNeeded: true })
            {
                await ctx.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                ctx.User = new ClaimsPrincipal(new ClaimsIdentity());
            }
            else if (refreshResult is RefreshTokenSuccess newTokens)
            {
                // I've got the new tokens
                // Everything that the OIDC authentication handler did
                // needs to be done again (right?)
            }
        }
    }

    await next(ctx);
});

问题解答

是否需要重新执行OIDC认证处理器的所有操作?

是,你需要重新执行核心的验证和身份映射操作,不需要重复执行读取发现端点、获取公钥这类一次性操作,但必须对新获取的id_token做合法性验证,执行声明映射,最终更新用户的ClaimsPrincipal和认证Cookie。

原因很直接:新令牌可能包含更新后的用户声明、权限信息,只有经过和登录时一致的验证逻辑,才能确保身份合法;同时必须把新的声明映射到用户身份对象中,让后续请求能使用最新的身份信息。

具体实现方式

推荐复用OIDC认证处理器的现有逻辑,避免重复造轮子,具体代码示例如下:

else if (refreshResult is RefreshTokenSuccess newTokens)
{
    // 获取OpenIdConnect认证处理器实例
    var handlerProvider = ctx.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
    var oidcHandler = await handlerProvider.GetHandlerAsync(ctx, OpenIdConnectDefaults.AuthenticationScheme) as OpenIdConnectHandler;
    
    if (oidcHandler == null)
    {
        // 处理处理器获取失败的情况,比如强制登出
        await ctx.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        ctx.User = new ClaimsPrincipal(new ClaimsIdentity());
        return;
    }

    // 1. 验证新id_token的合法性(复用OIDC配置的验证参数)
    var validationParams = oidcHandler.Options.TokenValidationParameters.Clone();
    var validationResult = await new JwtSecurityTokenHandler().ValidateTokenAsync(
        newTokens.IdToken, 
        validationParams
    );

    // 2. 执行声明映射(复用OIDC配置的ClaimActions)
    var claimsIdentity = new ClaimsIdentity(
        validationResult.Claims, 
        OpenIdConnectDefaults.AuthenticationScheme
    );
    oidcHandler.Options.ClaimActions.Run(validationResult.Claims, claimsIdentity);

    // 3. 创建新的ClaimsPrincipal
    var newPrincipal = new ClaimsPrincipal(claimsIdentity);

    // 4. 更新认证Cookie,持久化新的身份信息
    var authProps = new AuthenticationProperties
    {
        IsPersistent = ctx.User.Identity.IsAuthenticated,
        ExpiresUtc = DateTimeOffset.UtcNow.Add(oidcHandler.Options.RemoteAuthenticationOptions.CookieAuthenticationOptions.ExpireTimeSpan)
    };
    // 把新的access_token和refresh_token存入认证属性,方便后续使用
    authProps.Items["access_token"] = newTokens.AccessToken;
    authProps.Items["refresh_token"] = newTokens.RefreshToken;

    await ctx.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, newPrincipal, authProps);

    // 更新当前请求的User对象,让后续中间件能直接使用新身份
    ctx.User = newPrincipal;
}

关键注意事项

  • 必须验证令牌合法性:绝对不能直接信任刷新接口返回的令牌,必须验证签名、有效期、受众、颁发者等核心字段,避免伪造令牌的安全风险
  • 同步更新令牌存储:确保新的access_token和refresh_token被存储到正确的位置(比如Cookie、分布式缓存),保证后续请求能获取到有效令牌
  • 复用原有配置:所有验证规则、声明映射逻辑都要复用AddOpenIdConnect中配置的内容,避免出现和登录流程不一致的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 06:07:43