Spring Security授权码模式报错:Client authentication failed: client_id
问题描述
在学习《Spring Security in Action(第二版)》第14.2节「运行授权码授予类型」时,严格按照书中步骤操作,始终抛出以下异常:
org.springframework.security.oauth2.core.OAuth2AuthenticationException: Client authentication failed: client_id
操作流程
- 通过以下URL获取授权码:
http://localhost:8080/oauth2/authorize?response_type=code&client_id=client&scope=openid&redirect_uri=https://www.manning.com/authorized&code_challenge=Ys2R6lAx2idjbr_mVPYzweT2loaYVBPvUKBaeu3zDgo&code_challenge_method=S256
- 用curl请求交换令牌:
curl -X POST 'http://localhost:8080/oauth2/token?client_id=client&redirect_uri=https://www.manning.com/authorized&grant_type=authorization_code&code=lCC4um4ivSSAvXRtldrs8bWZV-Lre7HGOKjFnpifnZMTtZA6FGR7nxVXfNwVYX0koYfX0V7ejU9hm3birOzt_3nO1MAhiBuIx2rcWPQ9YXVqnUuWxGmWVrRfo0Q3gvR2&code_verifier=Uj0Kh6iiJvuEPKQcEnejWB9__bxCY-XwglkymMyXlJo' --header 'Authorization: Basic YmlsbDpwYXNzd29yZA=='
配置代码
@Configuration public class SecurityConfig { @Bean @Order(1) public SecurityFilterChain asFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration .applyDefaultSecurity(http); http.getConfigurer(OAuth2AuthorizationServerConfigurer.class) .oidc(Customizer.withDefaults()); http.exceptionHandling((e) -> e.authenticationEntryPoint( new LoginUrlAuthenticationEntryPoint("/login")) ); return http.build(); } @Bean @Order(2) public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http.formLogin(Customizer.withDefaults()); http.authorizeHttpRequests( c -> c.anyRequest().authenticated() ); return http.build(); } @Bean public UserDetailsService userDetailsService() { UserDetails userDetails = User.withUsername("bill") .password("password") .roles("USER") .build(); return new InMemoryUserDetailsManager(userDetails); } @Bean public PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } @Bean public RegisteredClientRepository registeredClientRepository() { RegisteredClient registeredClient = RegisteredClient .withId(UUID.randomUUID().toString()) .clientId("client") .clientSecret("secret") .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .redirectUri("https://www.manning.com/authorized") .tokenSettings( TokenSettings.builder() .accessTokenFormat(OAuth2TokenFormat.REFERENCE) .accessTokenTimeToLive(Duration.ofHours(24)) .build() ) .scope(OidcScopes.OPENID) .build(); return new InMemoryRegisteredClientRepository(registeredClient); } @Bean public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); KeyPair keyPair = keyPairGenerator.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); RSAKey rsaKey = new RSAKey.Builder(publicKey) .privateKey(privateKey) .keyID(UUID.randomUUID().toString()) .build(); JWKSet jwkSet = new JWKSet(rsaKey); return new ImmutableJWKSet<>(jwkSet); } @Bean public AuthorizationServerSettings authorizationServerSettings() { return AuthorizationServerSettings.builder().build(); } }
解决方案
异常核心原因是客户端身份验证凭证错误:
问题定位
你的Authorization头Basic YmlsbDpwYXNzd29yZA==解码后是bill:password,这是用户登录凭证,而非客户端的client_id:client_secret。根据配置,客户端的clientId是client,clientSecret是secret,正确的Base64编码凭证应为Y2xpZW50OnNlY3JldA==。
修复步骤
- 修改curl请求的
Authorization头:
curl -X POST 'http://localhost:8080/oauth2/token?client_id=client&redirect_uri=https://www.manning.com/authorized&grant_type=authorization_code&code=lCC4um4ivSSAvXRtldrs8bWZV-Lre7HGOKjFnpifnZMTtZA6FGR7nxVXfNwVYX0koYfX0V7ejU9hm3birOzt_3nO1MAhiBuIx2rcWPQ9YXVqnUuWxGmWVrRfo0Q3gvR2&code_verifier=Uj0Kh6iiJvuEPKQcEnejWB9__bxCY-XwglkymMyXlJo' --header 'Authorization: Basic Y2xpZW50OnNlY3JldA=='
- 额外验证:确保获取授权码和请求令牌时的
client_id、redirect_uri与配置完全一致。
内容的提问来源于stack exchange,提问作者fragilepriCe
相关产品推荐
相关产品推荐

