OAuth 2.0 Resource Server Bearer Tokens

Bearer Token Resolution

By default, Resource Server looks for a bearer token in the Authorization header. However, you can verify this token.

For example, you may have a need to read the bearer token from a custom header. To do so, you can wire an instance of ServerBearerTokenAuthenticationConverter into the DSL:

Custom Bearer Token Header
  • Java

  • Kotlin

ServerBearerTokenAuthenticationConverter converter = new ServerBearerTokenAuthenticationConverter();
converter.setBearerTokenHeaderName(HttpHeaders.PROXY_AUTHORIZATION);
http
    .oauth2ResourceServer(oauth2 -> oauth2
        .bearerTokenConverter(converter)
    );
val converter = ServerBearerTokenAuthenticationConverter()
converter.setBearerTokenHeaderName(HttpHeaders.PROXY_AUTHORIZATION)
return http {
    oauth2ResourceServer {
        bearerTokenConverter = converter
    }
}

Bearer Token Propagation

Now that you have a bearer token, you can pass that to downstream services. This is possible with ServerBearerExchangeFilterFunction:

  • Java

  • Kotlin

@Bean
public WebClient rest() {
    return WebClient.builder()
            .filter(new ServerBearerExchangeFilterFunction())
            .build();
}
@Bean
fun rest(): WebClient {
    return WebClient.builder()
            .filter(ServerBearerExchangeFilterFunction())
            .build()
}

When the WebClient shown in the preceding example performs requests, Spring Security looks up the current Authentication and extract any AbstractOAuth2Token credential. Then, it propagates that token in the Authorization header — for example:

  • Java

  • Kotlin

this.rest.get()
        .uri("https://other-service.example.com/endpoint")
        .retrieve()
        .bodyToMono(String.class)
this.rest.get()
        .uri("https://other-service.example.com/endpoint")
        .retrieve()
        .bodyToMono<String>()

The prececing example invokes the other-service.example.com/endpoint, adding the bearer token Authorization header for you.

In places where you need to override this behavior, you can supply the header yourself:

  • Java

  • Kotlin

this.rest.get()
        .uri("https://other-service.example.com/endpoint")
        .headers(headers -> headers.setBearerAuth(overridingToken))
        .retrieve()
        .bodyToMono(String.class)
rest.get()
        .uri("https://other-service.example.com/endpoint")
        .headers { it.setBearerAuth(overridingToken) }
        .retrieve()
        .bodyToMono<String>()

In this case, the filter falls back and forwards the request onto the rest of the web filter chain.

Unlike the OAuth 2.0 Client filter function, this filter function makes no attempt to renew the token, should it be expired.