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

Spring Authorization Server 1.0.0:不透明令牌调用introspect端点返回invalid_request

Spring Authorization Server 1.0.0 不透明令牌配置示例与问题排查

一、不透明令牌核心配置示例

1. 授权服务器配置

@Configuration
@EnableWebSecurity
public class AuthorizationServerConfig {

    @Bean
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
        http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
                .tokenIntrospectionEndpoint(tokenIntrospection -> tokenIntrospection
                        .authenticationProvider(new OAuth2TokenIntrospectionAuthenticationProvider(tokenStore())));
        return http.build();
    }

    @Bean
    public OAuth2TokenGenerator<?> tokenGenerator() {
        OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
        return new DelegatingOAuth2TokenGenerator(accessTokenGenerator);
    }

    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource());
    }

    @Bean
    public RegisteredClientRepository registeredClientRepository(DataSource dataSource) {
        return new JdbcRegisteredClientRepository(dataSource);
    }

    // 数据源配置需自行实现,确保oauth2_authorization、oauth2_registered_client等表已初始化
}

2. 客户端配置(代码示例)

需开启PKCE并指定不透明令牌格式:

@Bean
public RegisteredClientRepository registeredClientRepository() {
    RegisteredClient spaClient = RegisteredClient.withId(UUID.randomUUID().toString())
            .clientId("spa-client")
            .clientSecret("{bcrypt}$2a$10$...") // 替换为实际加密后的密钥
            .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
            .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
            .redirectUri("http://localhost:3000/callback")
            .scope(OAuth2ScopeConstants.OPENID)
            .scope("read")
            .clientSettings(ClientSettings.builder()
                    .requireProofKey(true) // 开启PKCE
                    .build())
            .tokenSettings(TokenSettings.builder()
                    .accessTokenFormat(OAuth2TokenFormat.REFERENCE) // 指定不透明令牌
                    .accessTokenTimeToLive(Duration.ofHours(1))
                    .build())
            .build();
    return new InMemoryRegisteredClientRepository(spaClient);
}

3. 资源服务器配置

@Configuration
@EnableWebSecurity
public class ResourceServerConfig {

    @Bean
    public SecurityFilterChain resourceServerSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(authorize -> authorize
                        .anyRequest().authenticated())
                .oauth2ResourceServer(oauth2 -> oauth2
                        .opaqueToken(opaque -> opaque
                                .introspectionUri("http://localhost:8080/oauth2/introspect")
                                .introspectionClientCredentials("spa-client", "client-secret")));
        return http.build();
    }
}

二、Introspect 端点返回 invalid_request 排查思路

  • 检查请求格式:必须用POST请求,Content-Type设为application/x-www-form-urlencoded,参数需包含token(待验证的访问令牌)、token_type_hint=access_token,客户端通过Basic Auth传递client_id和client_secret。
  • 验证令牌类型:确认待验证的是访问令牌而非ID令牌,ID令牌无法通过introspect端点验证。
  • 核对客户端权限:检查客户端是否被允许调用introspect端点,可查看数据库oauth2_registered_client表的client_settings字段,确认无权限限制配置。
  • 检查令牌状态:核对oauth2_authorization表中ticket字段与待验证令牌是否一致,同时确认expires_at字段晚于当前时间(令牌未过期)。
  • 调整日志级别:将org.springframework.security和org.springframework.security.oauth2的日志级别设为DEBUG,查看请求到达后的参数解析、身份验证流程细节,即使无错误日志也可能有关键信息。
  • 排查请求拦截:检查授权服务器是否有过滤器或网关拦截了introspect请求,比如不必要的CSRF防护(introspect端点默认无需CSRF验证)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:45:38