-
Notifications
You must be signed in to change notification settings - Fork 6k
OAuth2: No new token is requested when only password grant is used #10056
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi @geobreze, thanks for the report. Perhaps I'm misunderstanding and you can help clarify: Based on the code snippet from |
Hi @sjohnr, In our case, oauth2 backend had some issues with token refresh, but it was sending us both |
Thanks for the clarification there, that clears it up for me. Unfortunately, I don't see an easy way for the framework to solve your case while still providing the delegation-based strategy (loosely coupled) between different providers. Since yours is more of an edge case, I would suggest removing the @Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.password((builder) -> builder
.accessTokenResponseClient(createPasswordAccessTokenResponseClient())
.build())
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
private OAuth2AccessTokenResponseClient<OAuth2PasswordGrantRequest> createPasswordAccessTokenResponseClient() {
// Deprecated in 5.6. See note.
MapOAuth2AccessTokenResponseConverter defaultAccessTokenResponseConverter =
new MapOAuth2AccessTokenResponseConverter();
Converter<Map<String, String>, OAuth2AccessTokenResponse> noRefreshTokenConverter =
defaultAccessTokenResponseConverter
.andThen((accessTokenResponse) ->
OAuth2AccessTokenResponse.withResponse(accessTokenResponse)
.refreshToken(null)
.build());
OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseHttpMessageConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
accessTokenResponseHttpMessageConverter.setTokenResponseConverter(noRefreshTokenConverter);
RestTemplate restTemplate = new RestTemplate(
Arrays.asList(new FormHttpMessageConverter(), accessTokenResponseHttpMessageConverter));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
DefaultPasswordTokenResponseClient passwordTokenResponseClient = new DefaultPasswordTokenResponseClient();
passwordTokenResponseClient.setRestOperations(restTemplate);
return passwordTokenResponseClient;
} Note: Is this an acceptable workaround for your case? |
Thanks for the solution! We've applied another workaround for this case (error handling for token response, as advised in #10016). I just left this issue here to let you know about this (maybe, incredibly rare) edge case. Thanks for your input and your time investment, we will consider this workaround if something fails on production again 😃 |
Thanks. I will keep this in mind, as there is a theme around these APIs in the community right now. In this case though, I think the framework seems to be doing the sensible thing out of the box, and there are ways (some possibly even simpler than my suggestion) to customize for special cases. I'm going to close this for now, but feel free to re-open or add additional comments if you think of anything we missed in the discussion. |
You can create a wrapper class for the OAuth2AuthorizedClientManager and ensure the expired token is removed before it is used
|
Describe the bug
When
RefreshTokenOAuth2AuthorizedClientProvider
is not registered, butPasswordOAuth2AuthorizedClientProvider
does, next issue may happen. In case whenaccessToken
expired, but there isrefreshToken
in the context, no authorization is performed.This happens because of next block which assumes that
RefreshTokenOAuth2AuthorizedClientProvider
presents, which is not always true.spring-security/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/PasswordOAuth2AuthorizedClientProvider.java
Lines 95 to 101 in 7905409
To Reproduce
OAuth2AuthorizedClientProviderBuilder
, usepassword
, but notrefreshToken
providersExpected behavior
Password provider should get new token in case when there is no
RefreshTokenOAuth2AuthorizedClientProvider
.The text was updated successfully, but these errors were encountered: