Describe the bug It is possible to use "urn:ietf:params:oauth:grant-type:jwt-bearer" as a valid authorization-grant-type. However, Spring-Security does nothing if the grant_type uses the "short" notation : "jwt-bearer". In fact, the filter will just return an empty Mono in this situation)
The authentication POST call is then forged using the authorization-grant-type value as the "grant_type" field value. Some identity providers expect to see the exact string "jwt-bearer", which is problematic because there's no way to configure spring-security oauth client as such.
To Reproduce
Set a spring-security oauth-client project using those application.yml configurations. You'll see that nothing happens, regarding the authentication tokens fetch operations, even if we apply .oauth2Client() in a SecurityWebFilterChain bean.
Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application .class, args);
}
}
application.yml
security:
oauth2:
client:
registration:
<provider>:
client-authentication-method : client_secret_post
authorization-grant-type: jwt-bearer
client-id: <client id>
client-secret: <client secret>
Configuration Beans
@Configuration
@EnableWebFluxSecurity
public class OAuth2ClientSecurityConfiguration {
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientService) {
var jwtBearerAuthorizedClientProvider =
new JwtBearerReactiveOAuth2AuthorizedClientProvider();
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build();
var authorizedClientManager =
new DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
public SecurityWebFilterChain configure(ServerHttpSecurity http) {
return http
.oauth2Client()
.and()
.build();
}
@Bean
public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth.setDefaultClientRegistrationId(<provider>);
return WebClient.builder()
.filter(oauth)
.build();
}
}
Expected behavior The jwt-bearer flow should be enabled when using the authorization-grant-type "jwt-bearer", exactly how it actually does when we use "urn:ietf:params:oauth:grant-type:jwt-bearer"
Comment From: alexis-valois
It appears to be caused by that line, in JwtBearerReactiveOAuth2AuthorizedClientProvider.java : https://github.com/spring-projects/spring-security/blob/1631cac1506d7fdda1f3864357075af4965a78cd/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/JwtBearerReactiveOAuth2AuthorizedClientProvider.java#L71
AuthorizationGrantType.JWT_BEARER is a hardcoded value that evaluates to "urn:ietf:params:oauth:grant-type:jwt-bearer"
How about we just add another enty in AuthorizationGrantType, let's say
public static final AuthorizationGrantType JWT_BEARER_COMMON_NAME = new AuthorizationGrantType(
"jwt-bearer");
and just add a OR in the previous condition ?
I would gladly submit a pull request for it :)
Comment From: jgrandja
Closing as per comment