I have recently integrated Token Exchange into my project as I need to perform long-lived background tasks on behalf of the user. It exchanges the original access token from the user authentication for another with offline_access, which needs to be refreshed periodically (Keycloak).

Unfortunately, the current implementation of TokenExchangeOAuth2AuthorizedClientProvider doesn't support the refresh_token token type.

I managed to implement a custom version of the Token Exchange provider to support this and make it compatible with the Refresh Token provider, but It would be good to have it built in Spring Security as it is a common case.

Comment From: sjohnr

@icruces, thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add a minimal sample that reproduces this issue if you feel this is a genuine bug.

Having said that, I wonder if you are using an AuthorizedClientServiceOAuth2AuthorizedClientManager composed of TokenExchangeOAuth2AuthorizedClientProvider and RefreshTokenOAuth2AuthorizedClientProvider? I'm going to close this issue, but feel free to add additional comments.

Comment From: icruces

@sjohnr thanks for reply. I was actually asking for an enhancement. The TokenExchangeOAuth2AuthorizedClientProvider is not compatible with RefreshTokenOAuth2AuthorizedClientProvider as OAuth2AuthorizedClient created by the former doesn't store the refresh token in the new OAuth2AuthorizedClient:

        // TokenExchangeOAuth2AuthorizedClientProvider source code
        @Override
        @Nullable
    public OAuth2AuthorizedClient authorize(OAuth2AuthorizationContext context) {
        ...
                ...
                // tokenResponse.getRefreshToken() is not passed to the constructor so it is discarded

        return new OAuth2AuthorizedClient(clientRegistration, context.getPrincipal().getName(),
                tokenResponse.getAccessToken());
    }

Comment From: sjohnr

Hi @icruces. I'm not able to determine from the information you've provided whether you have tried setting things up correctly to have refresh tokens work. They should work if you are using OAuth2AuthorizedClientManager correctly. At the current time I don't believe the enhancement is needed and suspect that things are not set up correctly on your end. If you can provide a minimal example that demonstrates what you've tried, I will be able to either suggest what you are missing, or determine where an enhancement is required and we can go from there.

Comment From: sjohnr

@icruces thank you for bringing this up. I see in the spec (Section 2.2.1) that refresh tokens can be returned in offline access scenarios. I see what you are saying and am reopening this issue.

Comment From: icruces

@sjohnr Sounds great. Sorry, maybe I didn't express myself very well in English.

Comment From: sjohnr

Not at all. I read your first comment and didn't get the point, but your second comment made the point, I just didn't read it carefully enough.