Spring Authorization Server 1.0.0:不透明令牌调用introspect端点返回invalid_request
一、不透明令牌核心配置示例
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
相关产品推荐
相关产品推荐

