WebClient support should get new access token when an access token is expired and client_credentials is used
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.
Most helpful comment
Thanks @rwinch @dlesnef1 I'll take a look at it