Skip to content

RefreshTokenOAuth2AuthorizedClientProvider does not handle expired refresh token #7583

Closed
@janzyka

Description

@janzyka

Summary

Refresh tokens don't support timeouts - if refresh token expires application will keep trying to refresh access token through it forever.

Also all class around OAuth2 client are final which doesn't allow to fix the problem on my side temporary.

Actual Behavior

  1. App authorizes client and gets access & refresh tokens
  2. App is making requests through access token
  3. Access token expires, app is able to refresh
  4. Now refresh token expires (!)
  5. Attempt to refresh fails -> request fails
  6. Any subsequent access leads to attempt to refresh through expired refresh token
  7. Back to 5.

=> application will never recover

Expected Behavior

In order of preference

Option 1 - allow & handle refresh tokens expiry
Option 2 - add flag to optionally disable refresh tokens in PasswordOAuth2AuthorizedClientProvider
Option 3 - if refresh was attempted and failed remove client from authorizeClientRepository so the subsequent call starts from scratch allowing to recover

Idea 1 - don't make all classes final, it is difficult to add own behaviour. I remember nearly all classes in Spring used to be opened for extension.

Configuration

    @Bean
    public WebClient webClient(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService authorizedClientService) {

        AuthorizedClientServiceOAuth2AuthorizedClientManager manager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
        manager.setAuthorizedClientProvider(new DelegatingOAuth2AuthorizedClientProvider(
                new RefreshTokenOAuth2AuthorizedClientProvider(),
                new PasswordOAuth2AuthorizedClientProvider()));

        Map<String, Object> passwordAttributes = new HashMap<>();
        passwordAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, "user");
        passwordAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, "password");

        manager.setContextAttributesMapper(request -> passwordAttributes);

        ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = new ServletOAuth2AuthorizedClientExchangeFilterFunction(manager);

        oauth2.setDefaultClientRegistrationId("oauth-service-to-service-client");

        return WebClient.builder()
                .filter(oauth2)
                .apply(oauth2.oauth2Configuration())
                .build();
    }

Version

5.2

Sample

Metadata

Metadata

Assignees

Labels

in: oauth2An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions