Suppose you have the following configuration:
spring:
security:
oauth2:
client:
registration:
test-client:
provider: spring
client-id: aladdin
client-secret: "open sesame"
authorization-grant-type: client_credentials
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
scope: resource:read
provider:
spring:
authorization-uri: http://auth-server:9000/oauth/authorize
token-uri: http://auth-server:9000/oauth/token
In the example from the OP, the OAuth2AuthorizedClientManager
supports client_credentials
grant to make an access token request. This would be useful for ex. if we want to implement the following (fictional) endpoint:
@RestController
public class TokenController {
@GetMapping("/token")
public OAuth2AccessToken token(@RegisteredOAuth2AuthorizedClient("test-client") OAuth2AuthorizedClient testClient) {
return testClient.getAccessToken();
}
}
The OAuth2AuthorizedClientManager
provides the OAuth2AuthorizedClient
that is injected in this example. It can be configured with a custom converter as follows:
Note: The following is an expanded example adapted from the Client Credentials section of the reference documentation.
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
// @formatter:off
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials((builder) ->
builder.accessTokenResponseClient(clientCredentialsAccessTokenResponseClient())
.build())
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// @formatter:on
return authorizedClientManager;
}
@Bean
public OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsAccessTokenResponseClient() {
// @formatter:off
OAuth2ClientCredentialsGrantRequestEntityConverter requestEntityConverter =
new OAuth2ClientCredentialsGrantRequestEntityConverter();
requestEntityConverter.setHeadersConverter(headersConverter());
DefaultClientCredentialsTokenResponseClient accessTokenResponseClient =
new DefaultClientCredentialsTokenResponseClient();
accessTokenResponseClient.setRequestEntityConverter(requestEntityConverter);
// @formatter:on
return accessTokenResponseClient;
}
private static <T extends AbstractOAuth2AuthorizationGrantRequest> Converter<T, HttpHeaders> headersConverter() {
// @formatter:off
Converter<T, ClientRegistration> clientRegistrationConverter =
AbstractOAuth2AuthorizationGrantRequest::getClientRegistration;
return clientRegistrationConverter
.andThen((clientRegistration) -> {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8));
headers.setContentType(MediaType.valueOf(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8"));
headers.setBasicAuth(clientRegistration.getClientId(), clientRegistration.getClientSecret());
return headers;
});
// @formatter:on
}
If we wanted to support the authorization_code
grant for logging into the application, we could use the following configuration (with the above methods and @Bean
definitions contained within):
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests(authorizeRequests -> authorizeRequests
.anyRequest().authenticated())
.oauth2Login(oauth2Login -> oauth2Login
.tokenEndpoint(tokenEndpoint -> tokenEndpoint
.accessTokenResponseClient(authorizationCodeAccessTokenResponseClient())));
// @formatter:on
return http.build();
}
@Bean
public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeAccessTokenResponseClient() {
// @formatter:off
OAuth2AuthorizationCodeGrantRequestEntityConverter requestEntityConverter =
new OAuth2AuthorizationCodeGrantRequestEntityConverter();
requestEntityConverter.setHeadersConverter(headersConverter());
DefaultAuthorizationCodeTokenResponseClient accessTokenResponseClient =
new DefaultAuthorizationCodeTokenResponseClient();
accessTokenResponseClient.setRequestEntityConverter(requestEntityConverter);
// @formatter:on
return accessTokenResponseClient;
}
// ...
}