Spring-security: WebClient support should get new access token when expired and client_credentials

Created on 21 Sep 2018  路  17Comments  路  Source: spring-projects/spring-security

Summary

WebClient support should get new access token when an access token is expired and client_credentials is used

oauth2 backported enhancement

Most helpful comment

Thanks @rwinch @dlesnef1 I'll take a look at it

All 17 comments

I don't think this behavior should be enabled by default since the OAuth 2.0 spec actually discourages the issuing/use of refresh tokens with client credentials grant - see https://tools.ietf.org/html/rfc6749#section-4.4.3.

This should probably be made as opt-in feature.

@rwinch I think there was a misunderstanding of my original question.

My Authentication Server does not return a refresh_token, only the standard response outlined by https://tools.ietf.org/html/rfc6749#section-4.4.3.

What I am attempting to do is configure WebClient (make a Bean) such that it makes the access request to the Authentication Server under the hood and remembers the access_token. Then I can autowire in the Bean and make requests to a protected resource server without having to provide the access_token directly.

Here is the old configuration for a RestTemplate Bean.

@Bean
    @Qualifier("blah")
    public RestTemplate oAuthRestTemplate() {
        ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
        resourceDetails.setClientId(clientId);
        resourceDetails.setClientSecret(clientSecret);
        resourceDetails.setAccessTokenUri(accessTokenUri);
        resourceDetails.setScope(scopes);
        resourceDetails.setGrantType("client_credentials");

        RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, new DefaultOAuth2ClientContext());
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
        return restTemplate;
    }

By refreshing the token, I mean it will be the configured WebClient's job to notice the access_token is expiring (the response includes the default "expires_in" field) and make a request to the Authentication Server to reset the token.

@dlesnef1 You have described what I view this feature as doing. I have updated the title to make it more clear that it isn't using a refresh token. Any interest in submitting a PR for this?

Hey @rwinch I will definitely give it a go. I read the contributing guide and peaked at some other PRs.

Any advice on getting started would be appreciated, but I will begin looking at the code soon.

You will want to update it in the following locations:

We probably want to make it clear in the naming and in the method it is invoked that this is technically not a refresh, so rather than placing it in a method talking about refresh, then we would want to place it in a method which gets a new access token when client credentials is expired.

If you need feedback you can create a PR and I can take a look from there. Feel free to reach out with questions too

Hi all, I've just hit this issue too. I'm using an UnAuthenticatedServerOAuth2AuthorizedClientRepository as I'm doing server to server Oauth 2 using a client credentials grant. That repository stores the access token in a hash map and continually reuses it, which is great until the token expires as there's no code in place to get a new token.

I can work around it by creating a wrapper for the authorised client repository which checks the token expiry when it's loaded. However I agree this functionality should be in the exchange filter function.

@dlesnef1 Any progress on a PR? If not, I can take a look.

@warrenbailey Thanks for the offer to look at this. So I don't forget to respond...Let's give @dlesnef1 a week to respond. If you don't hear anything, I think it is safe for you to take the PR

@dlesnef1 Any updates on this? If not, can we let @warrenbailey take a look?

Hey, sorry for the late delay. Please use @warrenbailey's work as I will not be able to finish this before they are able too.

Thanks @rwinch @dlesnef1 I'll take a look at it

I've had a go at fixing it. I've tested the fix against my problem and it solves it. However I'd value some feedback on PR as Reactive is pretty new to me.

@rwinch will this feature be back ported to spring security 5.1.x and included in spring boot 2.1.x?

@xyloman This is a new feature so it won't be back-ported to 5.1.x.

@jgrandja we are still dealing with client credentials expiring and the tokens not being refreshed when on spring boot 2.1.10.RELEASE is there a workaround or plans to support refreshing client credential tokens when they are expired in spring security 5.1.x?

@jgrandja I should also add that upgrading to spring boot 2.2.1 would likely fix this issue but we are needing spring cloud as well in all use cases.

I upgraded to spring boot 2.2.1 version and i still face the same issue... WebClient couldn't make successful call to the resource-server once the token that it received for the first time (during boot-up) is expired

Apologies @xyloman, as this should have been back ported to 5.1.x. I reviewed the changes again and this is a patch fix so I went ahead and back-ported via #7685.

Was this page helpful?
0 / 5 - 0 ratings