Spring Boot Authorization Server giving Invalid Client Error for Client Credentials grant type with client secret basic auth method

huangapple go评论59阅读模式
英文:

Spring Boot Authorization Server giving Invalid Client Error for Client Credentials grant type with client secret basic auth method

问题

当我在后端将客户端身份验证方法设置为client_secret_post并通过Postman发送以下请求时,我会收到访问令牌。

但是,当我将身份验证方法更改为client_secret_basic并通过Postman发送以下请求时,我会收到invalid_client错误。

根据我的理解,当我们将client_secret_basic作为客户端身份验证方法时,我们应该在Authorization标头中以Base64编码的格式发送clientId和clientSecret。这种理解是否正确,或者我漏掉了什么?

英文:

I have Spring Boot Authorization Server (version 1.0.1) running. When I set the client authentication method as client_secret_post at the backend and send the following request via Postman, I'm getting the access token.

Spring Boot Authorization Server giving Invalid Client Error for Client Credentials grant type with client secret basic auth method

Edit: I'm also attaching the screenshot of MySQL database entry for this client to show that the client_authentication_method in this case is set to client_secret_post. The client_secret here is hashed using Bcrypt Password Encoder.

Spring Boot Authorization Server giving Invalid Client Error for Client Credentials grant type with client secret basic auth method

However, when I change the authentication method to client_secret_basic and send the following request via Postman, I'm getting invalid_client error.

Spring Boot Authorization Server giving Invalid Client Error for Client Credentials grant type with client secret basic auth method

Spring Boot Authorization Server giving Invalid Client Error for Client Credentials grant type with client secret basic auth method

Edit: I'm also attaching the screenshot of MySQL database entry for this client to show that the client_authentication_method is set to client_secret_basic. The client_secret here is hashed using Bcrypt Password Encoder.

Spring Boot Authorization Server giving Invalid Client Error for Client Credentials grant type with client secret basic auth method

I'm attaching the console output of HTTP request and error response for reference here.

Spring Boot Authorization Server giving Invalid Client Error for Client Credentials grant type with client secret basic auth method

Here are the necessary codes and configuration snippets:

RegisteredClientRepository implementation:

@Service
public class ClientService implements RegisteredClientRepository {

 private static final Logger log = LogManager.getLogger();

 @Autowired
 ClientRepository clientRepository;

 @Override
 public void save(RegisteredClient registeredClient) {
 }

 @Override
 public RegisteredClient findById(String id) {
	return this.clientRepository.findByClientId(id);
 }

 @Override
 public RegisteredClient findByClientId(String clientId) {
	return this.clientRepository.findByClientId(clientId);
 }

}

Authorization Server Configuraion:

@Configuration
public class AvocadoAuthorizationServerConfiguration {

@Autowired
CryptoUtils cryptoUtils;

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer();
	http
		.apply(authorizationServerConfigurer)
		.and()
		.formLogin(Customizer.withDefaults());
	return http.build();
}

@Bean
public PasswordEncoder userPasswordEncoder() {
	return new BCryptPasswordEncoder(8);
}

@Bean 
public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
	RSAPublicKey publicKey = (RSAPublicKey) cryptoUtils.getPublicKey();
	RSAPrivateKey privateKey = (RSAPrivateKey) cryptoUtils.getPrivateKey();
	RSAKey rsaKey = new RSAKey.Builder(publicKey)
			.privateKey(privateKey)
			.keyID(UUID.randomUUID().toString())
			.build();
	JWKSet jwkSet = new JWKSet(rsaKey);
	return new ImmutableJWKSet<>(jwkSet);
}

@Bean
public JwtDecoder jwtDecoder() {
	RSAPublicKey publicKey = null;
	try {
		publicKey = (RSAPublicKey) cryptoUtils.getPublicKey();
	} catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e) {
		e.printStackTrace();
	}
	return NimbusJwtDecoder.withPublicKey(publicKey).build();
}
}

As per my understanding, when we are using client_secret_basic as the client authentication method, we are supposed to send clientId and clientSecret in base64 encoded format in the Authorization header. Is this understanding correct or am I missing something?

答案1

得分: 1

如果您的RegisteredClient未将client_secret_basic作为允许的clientAuthenticationMethod,将会收到invalid_client错误。请确保两者都已指定。例如,在使用内存客户端(仅供演示目的)时:

	@Bean
	public RegisteredClientRepository registeredClientRepository() {
		RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
				.clientId("messaging-client")
				.clientSecret("{noop}secret")
				// **** 确保如果需要两种方法,都将它们允许
				.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
				.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
				// ****
				.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
				.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
				.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
				.authorizationGrantType(OAuth2DeviceCode.GRANT_TYPE)
				.redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
				.redirectUri("http://127.0.0.1:8080/authorized")
				.scope(OidcScopes.OPENID)
				.scope(OidcScopes.PROFILE)
				.scope("message.read")
				.scope("message.write")
				.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
				.build();

		return new InMemoryRegisteredClientRepository(registeredClient);
	}

如果问题仍未解决,请分享您的配置。

英文:

You will get the invalid_client error if your RegisteredClient does not have client_secret_basic as an allowed clientAuthenticationMethod. Make sure you have both specified. For example, when using an in-memory client (for demonstration purposes):

	@Bean
	public RegisteredClientRepository registeredClientRepository() {
		RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
				.clientId("messaging-client")
				.clientSecret("{noop}secret")
				// **** Ensure both are allowed if both methods are needed
				.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
				.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
				// ****
				.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
				.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
				.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
				.authorizationGrantType(OAuth2DeviceCode.GRANT_TYPE)
				.redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
				.redirectUri("http://127.0.0.1:8080/authorized")
				.scope(OidcScopes.OPENID)
				.scope(OidcScopes.PROFILE)
				.scope("message.read")
				.scope("message.write")
				.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
				.build();

		return new InMemoryRegisteredClientRepository(registeredClient);
	}

If that does not solve your issue, please share your configuration.

huangapple
  • 本文由 发表于 2023年2月27日 05:56:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75575243.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定