-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
Client id inclusion for refresh token grant is not consistent between servlet and reactive stacks #14811
Comments
@benba thanks for reaching out! This is a fairly nuanced topic, particularly because (as you pointed out) the specification doesn't paint a perfectly clear picture. A reading of the core OAuth 2.0 spec suggests that whether the
I'm not clear why Auth0 and Curity would use it as their default example, but I'm sure they both support In any case, I think this issue extends beyond just refresh tokens to other grant types as well. I believe the reactive side has it mostly correct. Of the currently supported client authentication methods ( Before we go any farther, we would need to identify whether making a change here would be a breaking change and have an impact on users. It doesn't seem likely that clients would break if they start providing a In the meantime, you can of course work around the issue by customizing the token request parameters with the following configuration: @Bean
public OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenAccessTokenResponseClient() {
var requestEntityConverter = new OAuth2RefreshTokenGrantRequestEntityConverter();
requestEntityConverter.addParametersConverter(parametersConverter());
var accessTokenResponseClient = new DefaultRefreshTokenTokenResponseClient();
accessTokenResponseClient.setRequestEntityConverter(requestEntityConverter);
return accessTokenResponseClient;
}
private static Converter<OAuth2RefreshTokenGrantRequest, MultiValueMap<String, String>> parametersConverter() {
return (grantRequest) -> {
var clientRegistration = grantRequest.getClientRegistration();
var clientAuthenticationMethod = clientRegistration.getClientAuthenticationMethod();
var parameters = new LinkedMultiValueMap<String, String>();
if (!ClientAuthenticationMethod.CLIENT_SECRET_BASIC.equals(clientAuthenticationMethod)) {
parameters.set(OAuth2ParameterNames.CLIENT_ID, clientRegistration.getClientId());
}
return parameters;
};
} I'll spend some time thinking about this, but let me know if you have any additional thoughts. |
I had the same problem by using oauth2-login with a public-pkce client and keycloak as idp. Thanks for the workaround @sjohnr |
This commit refactors and aligns usage of the parametersConverter in AbstractWebClientReactiveOAuth2AccessTokenResponseClient with the same capability in AbstractOAuth2AuthorizationGrantRequestEntityConverter in order to align Reactive with Servlet for better consistency. Closes spring-projectsgh-14811
Apologies for the noise on this issue, I mixed up this issue # with gh-11298. By way of an update, my goal is to partially address this issue via work on theme issue gh-15299. However, due to needing to remain backwards compatible, I don't anticipate directly addressing this issue with changes to the existing |
Hi @sjohnr,
IMHO it has to be
|
Thanks for the update @marbon87. I think that makes sense for the workaround. |
Hi everyone. I have merged gh-15337 which includes new implementations of Please try out the changes in @Configuration
@EnableWebSecurity
public class SecurityConfiguration {
// ...
@Bean
public OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenAccessTokenResponseClient() {
return new RestClientRefreshTokenTokenResponseClient();
}
} |
Hey @sjohnr, sorry, but how does this solve the root problem of this issue, that the client-id is missing in the refresh request? |
Hi @marbon87, As mentioned in this comment, we cannot adjust the behavior in the |
Hey @sjohnr , sorry my unit-test had a smell. After i fixed that, everything is working fine with the new RestClientRefreshTokenTokenResponseClient |
Thanks for the feedback @marbon87. As mentioned in this comment, directly addressing this issue would break passivity. Instead, users on the servlet stack can opt-in to |
When a refresh token grant exchange occurs with a ClientAuthentication Method set to
NONE
On a servlet appliction, the
client_id
field will be missing because it is only added if theClientAuthenticationMethod
is set toCLIENT_SECRET_POST
: see OAuth2Refresh TokenGrantRequestEntityConverterOn a reactive applicatoin, the behavior is not consistent because the
client_id
field is always added except ifClientAuthenticationMethod
is set toCLIENT_SECRET_BASIC
: see AbstractWebClientReactiveOAuth2AccessTokenResponseClientOur internal IDP use only public clients but
client_id
parameter is mandatory, so the reactive default seems better for us, but maybe there are other cases that would make the current servlet default better?I don't see any clear answer for the specification, some implementations (like Auth0 or Curity) seems to always ask a
client_id
, but other don't (like Okta).Maybe the
client_id
inclusion should depend from another property of the client registration instead of theClientAuthenticationMethod
?The text was updated successfully, but these errors were encountered: