Reputation: 1330
I'm trying to replace the deprecated OAuth2RestTemplate
with a custom interceptor approach for adding an x-access-token header
using the ClientHttpRequestInterceptor
in Spring Batch. My goal is to configure a RestTemplate that supports OAuth2 client credentials authorization with minimal changes to our existing code.
I’ve configured the necessary beans as follows:
Security Configuration
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/", "/public/**").permitAll()
.anyRequest().permitAll())
.oauth2Client(withDefaults());
return http.build();
}
}
Client Registration Configuration:
@Configuration
public class ClientRegistrationConfig {
@Bean
public ClientRegistrationRepository clientRegistrationRepository(ConfigModel configModel) {
ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("my-oauth2-client")
.tokenUri(configModel.getGatewayAuthTokenUri())
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.clientId(configModel.getGatewayAuthClientId())
.clientSecret(configModel.getGatewayAuthClientSecret())
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.scope("openid")
.build();
return new InMemoryClientRegistrationRepository(clientRegistration);
}
}
RestTemplate Configuration
public class RestTemplateConfig {
@Bean(name = "gatewayRestTemplate")
public RestTemplate gatewayRestTemplate(
RestTemplateBuilder builder,
OAuth2AuthorizedClientManager authorizedClientManager,
ClientRegistrationRepository clientRegistrationRepository) {
ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId("my-oauth2-client");
ClientHttpRequestInterceptor interceptor = new OAuth2ClientInterceptor(authorizedClientManager, clientRegistration);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(10000, TimeUnit.MILLISECONDS)
.setResponseTimeout(10000, TimeUnit.MILLISECONDS)
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
factory.setConnectTimeout(Duration.ofMillis(13000));
return builder
.requestFactory(() -> factory)
.additionalInterceptors(interceptor) // Adding a custom interceptor for setting the x-access-token
.build();
}
}
Custom Interceptor
public class OAuth2ClientInterceptor implements ClientHttpRequestInterceptor {
private final OAuth2AuthorizedClientManager manager;
private final ClientRegistration clientRegistration;
public OAuth2ClientInterceptor(OAuth2AuthorizedClientManager manager, ClientRegistration clientRegistration) {
this.manager = manager;
this.clientRegistration = clientRegistration;
}
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().set("x-access-token", getAccessToken());
return execution.execute(request, body);
}
private String getAccessToken() {
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
.withClientRegistrationId(clientRegistration.getRegistrationId())
.principal(clientRegistration.getClientId())
.build();
OAuth2AuthorizedClient client = manager.authorize(authorizeRequest);
Assert.notNull(client, () -> "Authorized client failed for Registration id: '" + clientRegistration.getRegistrationId() + "', returned client is null");
return client.getAccessToken().getTokenValue();
}
}
When making a restTemplate.exchange()
call within a Spring Batch Job, the authorize()
method in the OAuth2AuthorizedClientManager
throws this exception servletRequest cannot be null
This exception originates from the authorize()
of DefaultOAuth2AuthorizedClientManager
I’ve also explored RestClient
and WebClient
approaches, but switching to these requires larger refactoring, which I’d like to avoid for now.
I’ve referred to the following resources but couldn’t find a solution specific to Spring Batch
Spring Security OAuth2 Client Documentation
How to configure OAuth2AuthorizedClientManager
or handle the servletRequest issue
to make this interceptor-based approach work in Spring Batch?
Any suggestions or alternative solutions that work well in this context are appreciated!
Upvotes: 1
Views: 206