Reputation: 7739
I am trying to set up a Resource server using the built-in OAuth support in Spring Security. I need to inject a new request header into every request that is sent from the Resource server to the Auth service. How can I do that?
Use case
The Auth service sits behind a corporate API Gateway forwarding service, like so:
Resource API > API Gateway > Auth API
Every request sent through the API Gateway requires an additional header to authenticate the client to the Gateway service. How can I inject this header? The Auth API implementation is otherwise a standard OIDC setup.
My setup
I have added spring security oauth2 to my Gradle build:
implementation 'org.springframework.security:spring-security-config'
implementation 'org.springframework.security:spring-security-oauth2-resource-server'
implementation 'org.springframework.security:spring-security-oauth2-jose'
I have configured the issuer URI in Spring Security, as follows:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://auth/api/url
The problem
On app startup, I get the following exception:
java.lang.IllegalArgumentException: Unable to resolve the Configuration with the provided Issuer of "https://auth/api/url"
at org.springframework.security.oauth2.jwt.JwtDecoderProviderConfigurationUtils.getConfiguration(JwtDecoderProviderConfigurationUtils.java:99) ~[spring-security-oauth2-jose-5.4.2.jar:5.4.2]
Debugging the code for JwtDecoderProviderConfigurationUtils
, I see that it's failing because the API Gateway header is missing from the configuration request.
The problem is, I don't know how to modify the configuration utils to inject the API Gateway header. The request is built inline, using the URI only:
RequestEntity<Void> request = RequestEntity.get(uri).build();
ResponseEntity<Map<String, Object>> response = rest.exchange(request, STRING_OBJECT_MAP);
Map<String, Object> configuration = response.getBody();
The RestTemplate is hidden from my app code, so I don't see a way to add a client interceptor:
private static final RestTemplate rest = new RestTemplate();
In fact, the entire config utils class is package-level access, so I really can't do anything with it:
final class JwtDecoderProviderConfigurationUtils {
Everything else about the OIDC solution should be standard. How can I inject the required header without reinventing the entire Spring Security Oauth solution and all of the automagical configuration that it does?
Upvotes: 0
Views: 742
Reputation: 6168
All of the configurations enabled by setting any of the following properties:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri:
jwk-set-uri:
jws-algorithm:
public-key-location:
ultimately end up causing a JwtDecoder
bean to be created and automatically configured by Spring Boot (see OAuth2ResourceServerJwtConfiguration.JwtDecoderConfiguration
in the org.springframework.boot:spring-boot-autoconfigure
jar).
The easiest way to take control of this process and avoid the error would be to provide your own bean:
@Bean
JwtDecoder jwtDecoder() {
// ...
}
You could use the code in JwtDecoderProviderConfigurationUtils
as a starting point and add your own header to your own RestTemplate
, or you can simply provide an implementation directly and skip calling out to your auth server.
Upvotes: 0