For the latest stable version, please use Spring Security 6.4.1!

OAuth 2.0 Resource Server Bearer Tokens

Bearer Token Resolution

By default, Resource Server looks for a bearer token in the Authorization header. This, however, can be customized.

For example, you may have a need to read the bearer token from a custom header. To achieve this, you can wire an instance of ServerBearerTokenAuthenticationConverter into the DSL, as you can see in the following example:

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’re in possession of a bearer token, it might be handy to pass that to downstream services. This is quite simple with ServerBearerExchangeFilterFunction, which you can see in the following example:

  • 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 above WebClient is used to perform requests, Spring Security will look up the current Authentication and extract any AbstractOAuth2Token credential. Then, it will propagate 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>()

Will invoke the other-service.example.com/endpoint, adding the bearer token Authorization header for you.

In places where you need to override this behavior, it’s a simple matter of supplying the header yourself, like so:

  • 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 will fall back and simply forward 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. To obtain this level of support, please use the OAuth 2.0 Client filter.