You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.4 KiB
133 lines
3.4 KiB
= OAuth 2.0 Resource Server Bearer Tokens |
|
|
|
[[webflux-oauth2resourceserver-bearertoken-resolver]] |
|
== 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 |
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
ServerBearerTokenAuthenticationConverter converter = new ServerBearerTokenAuthenticationConverter(); |
|
converter.setBearerTokenHeaderName(HttpHeaders.PROXY_AUTHORIZATION); |
|
http |
|
.oauth2ResourceServer((oauth2) -> oauth2 |
|
.bearerTokenConverter(converter) |
|
); |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
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 javadoc:org.springframework.security.oauth2.server.resource.web.reactive.function.client.ServerBearerExchangeFilterFunction[]: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
@Bean |
|
public WebClient rest() { |
|
return WebClient.builder() |
|
.filter(new ServerBearerExchangeFilterFunction()) |
|
.build(); |
|
} |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
@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 javadoc:org.springframework.security.oauth2.core.AbstractOAuth2Token[] credential. |
|
Then, it propagates that token in the `Authorization` header -- for example: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
this.rest.get() |
|
.uri("https://other-service.example.com/endpoint") |
|
.retrieve() |
|
.bodyToMono(String.class) |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
this.rest.get() |
|
.uri("https://other-service.example.com/endpoint") |
|
.retrieve() |
|
.bodyToMono<String>() |
|
---- |
|
====== |
|
|
|
The preceding example invokes the `https://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: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,role="primary"] |
|
---- |
|
this.rest.get() |
|
.uri("https://other-service.example.com/endpoint") |
|
.headers((headers) -> headers.setBearerAuth(overridingToken)) |
|
.retrieve() |
|
.bodyToMono(String.class) |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,role="secondary"] |
|
---- |
|
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. |
|
|
|
[NOTE] |
|
==== |
|
Unlike the javadoc:org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction[OAuth 2.0 Client filter function], this filter function makes no attempt to renew the token, should it be expired. |
|
====
|
|
|