使用Spring OAuth2-Authorization-Server 1.2.2获取Token遇Access Denied问题
问题分析与修复方案
你的配置存在几个关键问题,导致返回Access Denied:
1. 客户端认证方法不匹配
你配置的客户端认证方法是CLIENT_SECRET_JWT,但你的请求是通过URL参数直接传递client_id和client_secret,这种方式对应的认证方法应该是CLIENT_SECRET_POST或者CLIENT_SECRET_BASIC。CLIENT_SECRET_JWT要求客户端生成JWT签名并携带认证,和你的请求方式完全不兼容。
2. 客户端密码未加密
Spring OAuth2 Authorization Server要求客户端密码必须加密存储,你直接明文设置clientSecret("secret")会导致认证失败,需要通过PasswordEncoder加密密码后再配置。
3. Client ID格式不匹配
配置中客户端ID是client-a(短横线分隔),但你的请求参数里是client_a(下划线分隔),两者不一致,服务端无法匹配到对应的客户端配置。
4. 冗余配置(建议修正)
client_credentials模式不需要授权同意和重定向URI,你配置的requireAuthorizationConsent(true)和redirectUri属于冗余设置,建议移除。
修改后的完整配置代码
@Configuration @EnableWebSecurity @Import(OAuth2AuthorizationServerConfiguration.class) public class AuthorizationServerConfig { @Bean public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http .csrf(Customizer.withDefaults()) .authorizeHttpRequests((authorize) -> authorize .requestMatchers("/oauth2/**").permitAll() ); return http.build(); } @Bean public OAuth2AuthorizationService authorizationService() { return new InMemoryOAuth2AuthorizationService(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public RegisteredClientRepository registeredClientRepository(PasswordEncoder passwordEncoder) { RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()) .clientId("client_a") // 和请求参数保持一致,改为下划线格式 .clientSecret(passwordEncoder.encode("secret")) // 对明文密码加密 .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST) // 匹配请求传递方式 .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) .scope("read") // 移除冗余的redirectUri和授权同意配置 .build(); return new InMemoryRegisteredClientRepository(registeredClient); } @Bean public JWKSource<SecurityContext> jwkSource() { RSAKey rsaKey = Jwks.generateRsa(); JWKSet jwkSet = new JWKSet(rsaKey); return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet); } @Bean public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) { return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource); } @Bean public AuthorizationServerSettings authorizationServerSettings() { return AuthorizationServerSettings.builder().build(); } }
请求建议
修改配置后,建议将client_id和client_secret放在POST请求体中(表单参数),更符合CLIENT_SECRET_POST的规范:
curl -X POST http://localhost:9000/oauth2/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "scope=read" \ -d "client_id=client_a" \ -d "client_secret=secret"
内容的提问来源于stack exchange,提问作者user23714896
相关产品推荐
相关产品推荐

