spring-security: Introduce Reactive OAuth2Authorization success/failure handlers
Summary
When an OAuth2 Client sends a token to a downstream OAuth2 Resource Server, and the OAuth2 Resource Server returns an HTTP 401 response, I would like to prevent the OAuth2 Client from sending that same token in future requests (and instead retrieve a new token for future requests).
Currently, spring-security-oauth2-client provides good support for re-retrieving/refreshing tokens before they expire. However, spring-security-oauth2-client does not provide good support for re-retrieving/refreshing access tokens when they have become invalid for reasons other than expiration. A good signal that a token is no longer valid is when an OAuth2 Resource Server returns an HTTP 401 response to the client.
Both ServerOAuth2AuthorizedClientRepository and ReactiveOAuth2AuthorizedClientService provide a removeAuthorizedClient method to remove the cached OAuth2AuthorizedClient. It would be nice if spring-security-oauth2-client provided something that actually called that method when an HTTP 401 response is received from an OAuth2 Resource Server.
A possible implementation might be:
- the
DefaultReactiveOAuth2AuthorizedClientManager(and the futureAuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerfrom #7589) could put aMono<Void>in the subscriber context that will remove the token from the cache when subscribedDefaultReactiveOAuth2AuthorizedClientManagerwould put aMono<Void>that invokes itsServerOAuth2AuthorizedClientRepository.removeAuthorizedClientAuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerwould put aMono<Void>that invokes itsReactiveOAuth2AuthorizedClientService.removeAuthorizedClient
- A new
ExchangeFilterFunction(or one of the existing ones) checks for HTTP 401 responses, and chains theMono<Void>from step 1 if it exists- usage of the subscriber context would decouple the
ExchangeFilterFunctionfrom the implementation of how to remove the cached authorized client (i.e. separate filter function implementations would not be needed depending on whether aServerOAuth2AuthorizedClientRepositoryorReactiveOAuth2AuthorizedClientServiceis being used to persistOAuth2AuthorizedClients) - It would also allow other places downstream (e.g. non-WebClient related functionality, like WebSocketClient) to potentially invalidate the authorized client, without direct knowledge of exactly how it is persisted, other than just subscribing to a
Mono<Void>)
- usage of the subscriber context would decouple the
(After looking at this a bit more, I realize the above approach probably won’t work, since anything put into the subscriber context by a ReactiveOAuth2AuthorizedClientManager wouldn’t actually be visible downstream in an ExchangeFilterFunction . So, something else is needed. Perhaps something in ServerOAuth2AuthorizedClientExchangeFilterFunction)
Actual Behavior
spring-security-oauth2-client continues to reuse an OAuth2 token, even after an OAuth2 Resource server has returned a 401 response, which usually indicates the token is invalid.
Expected Behavior
spring-security-oauth2-client removes the cached token after an OAuth2 Resource server has returned a 401 response. Future requests will trigger a re-retrieval of a new token.
Configuration
- spring-security-oauth2-client
- using either
DefaultReactiveOAuth2AuthorizedClientManagerorAuthorizedClientServiceReactiveOAuth2AuthorizedClientManagerfrom #7589 - WebClient or WebSocketClient usage downstream
Version
5.2.1.RELEASE
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 1
- Comments: 17 (17 by maintainers)
Commits related to this issue
- Introduce Reactive OAuth2Authorization success/failure handlers All ReactiveOAuth2AuthorizedClientManagers now have authorization success/failure handlers. A success handler is provided to save autho... — committed to philsttr/spring-security by philsttr 5 years ago
- Resolve OAuth2Error from WWW-Authenticate header Issue gh-7699 — committed to spring-projects/spring-security by jgrandja 4 years ago
- Fix package tangles Issue #7699 #7840 — committed to spring-projects/spring-security by jgrandja 4 years ago
- Polish Fix package tangles Issue #7699 #7840 — committed to spring-projects/spring-security by jgrandja 4 years ago
@philsttr To make things easier during the review process, let’s focus on the reactive implementation first and submit in it’s own PR. After it’s merged, we can switch to the Servlet implementation.
(6) I feel option A makes the most sense. I would introduce a new exception named
ClientAuthorizationException. This exception would serve as the base exception for all authorization related errors for client. The new hierarchy would be:OAuth2AuthorizationException<-ClientAuthorizationException<-ClientAuthorizationRequiredExceptionWe could than push
ClientAuthorizationRequiredException.clientRegistrationIdup toClientAuthorizationException.How does that sound?
Just a heads up that I’ll be off for the holidays between Dec 23 - Jan 3 (inclusive). And next week I’m pretty swamped as well. I will be available next week but just wanted to let you know so you are not rushing to implement this feature 😃 Thanks again for taking this on. It will be a valuable add to client.