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

Spring Authorization Server 1.1.1中OIDC的sid与auth_time为空致刷新报错

解决方案与auth_time配置建议

问题回顾

你提到升级到spring-boot-starter-oauth2-authorization-server 3.1.3后,刷新令牌时的500错误已解决——这是因为新版本修复了旧版本中JwtGenerator在刷新流程中无法正确从原IdToken读取sid和auth_time的问题,现在这两个claim会自动继承自首次认证的IdToken,无需手动添加。

配置auth_time实现定时重认证

要利用auth_time实现定时强制重认证,需结合OIDC标准的max_age参数和授权服务器的会话管理策略,具体步骤如下:

  1. 客户端请求触发重认证检查
    客户端在发起授权请求时,携带max_age参数(例如max_age=3600),表示若用户上次认证时间距当前超过3600秒,必须重新进行身份验证。

  2. 授权服务器端会话与认证时间管理

    • 配置会话超时:通过SecurityFilterChain中的会话管理规则,设置会话的最大空闲时间或绝对过期时间,示例:
      @Bean
      public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
          http
              .sessionManagement(session -> session
                  .sessionFixation().migrateSession()
                  .maximumSessions(1)
                  .expiredUrl("/login?expired")
                  .maxSessionsPreventsLogin(true)
              );
          // 其他授权服务器配置...
          return http.build();
      }
      
    • 确保auth_time正确生成:升级后的版本会在首次认证时自动设置auth_time,若需自定义(比如统一用UTC时间),可在JwtTokenCustomizer中补充:
      if (OidcParameterNames.ID_TOKEN.equalsIgnoreCase(context.getTokenType().getValue())) {
          if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(context.getAuthorizationGrantType())) {
              // 首次认证时设置auth_time为当前时间戳(秒级)
              long authTime = Instant.now().getEpochSecond();
              context.getClaims().claim(IdTokenClaimNames.AUTH_TIME, authTime);
          }
      }
      
  3. 资源服务器验证auth_time
    资源服务器在接收令牌时,需验证auth_time是否满足客户端指定的max_age要求,拒绝超时的令牌。可通过自定义JWT验证逻辑实现:

    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(new JwtGrantedAuthoritiesConverter());
        converter.setPrincipalClaimName("sub");
        // 添加auth_time验证逻辑
        converter.setJwtValidator(jwt -> {
            Instant authTime = jwt.getClaimAsInstant(IdTokenClaimNames.AUTH_TIME);
            if (authTime == null) {
                return OAuth2Error.withErrorCode(OAuth2ErrorCodes.INVALID_TOKEN)
                    .description("Missing auth_time claim")
                    .build();
            }
            // 假设从请求参数或客户端配置获取max_age
            long maxAge = 3600;
            if (Instant.now().minusSeconds(maxAge).isAfter(authTime)) {
                return OAuth2Error.withErrorCode(OAuth2ErrorCodes.INVALID_TOKEN)
                    .description("Authentication expired")
                    .build();
            }
            return OAuth2AuthenticationValidatorResult.success();
        });
        return converter;
    }
    
  4. 完善重认证流程

    • 配置客户端的postLogoutRedirectUri,确保用户重认证后能正确跳转回业务页面。
    • 授权服务器端配置logoutSuccessUrl,处理会话过期或重认证后的跳转逻辑。

关键注意事项

  • auth_time在刷新令牌时会自动继承首次认证的值,无需手动修改,确保用户认证状态的一致性。
  • 定时重认证的触发依赖客户端主动携带max_age参数,授权服务器不会主动强制重认证,除非会话已过期。
  • 若需全局强制重认证策略,可自定义OAuth2AuthorizationService,在刷新令牌时检查auth_time是否超过阈值,拒绝刷新请求并引导用户重新认证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 12:12:08