diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java index da90d58a16..fff6222bb6 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ import org.springframework.web.reactive.function.BodyExtractor; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec; /** * Abstract base class for all of the {@code WebClientReactive*TokenResponseClient}s that @@ -70,6 +71,8 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient> requestEntityConverter = this::validatingPopulateRequest; + private Converter headersConverter = this::populateTokenRequestHeaders; private Converter> parametersConverter = this::populateTokenRequestParameters; @@ -84,15 +87,7 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient getTokenResponse(T grantRequest) { Assert.notNull(grantRequest, "grantRequest cannot be null"); // @formatter:off - return Mono.defer(() -> this.webClient.post() - .uri(clientRegistration(grantRequest).getProviderDetails().getTokenUri()) - .headers((headers) -> { - HttpHeaders headersToAdd = getHeadersConverter().convert(grantRequest); - if (headersToAdd != null) { - headers.addAll(headersToAdd); - } - }) - .body(createTokenRequestBody(grantRequest)) + return Mono.defer(() -> this.requestEntityConverter.convert(grantRequest) .exchange() .flatMap((response) -> readTokenResponse(grantRequest, response)) ); @@ -106,6 +101,34 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient validatingPopulateRequest(T grantRequest) { + validateClientAuthenticationMethod(grantRequest); + return populateRequest(grantRequest); + } + + private void validateClientAuthenticationMethod(T grantRequest) { + ClientRegistration clientRegistration = grantRequest.getClientRegistration(); + ClientAuthenticationMethod clientAuthenticationMethod = clientRegistration.getClientAuthenticationMethod(); + boolean supportedClientAuthenticationMethod = clientAuthenticationMethod.equals(ClientAuthenticationMethod.NONE) + || clientAuthenticationMethod.equals(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) + || clientAuthenticationMethod.equals(ClientAuthenticationMethod.CLIENT_SECRET_POST); + if (!supportedClientAuthenticationMethod) { + throw new IllegalArgumentException(String.format( + "This class supports `client_secret_basic`, `client_secret_post`, and `none` by default. Client [%s] is using [%s] instead. Please use a supported client authentication method, or use `set/addParametersConverter` or `set/addHeadersConverter` to supply an instance that supports [%s].", + clientRegistration.getRegistrationId(), clientAuthenticationMethod, clientAuthenticationMethod)); + } + } + + private RequestHeadersSpec populateRequest(T grantRequest) { + return this.webClient.post().uri(clientRegistration(grantRequest).getProviderDetails().getTokenUri()) + .headers((headers) -> { + HttpHeaders headersToAdd = getHeadersConverter().convert(grantRequest); + if (headersToAdd != null) { + headers.addAll(headersToAdd); + } + }).body(createTokenRequestBody(grantRequest)); + } + /** * Populates the headers for the token request. * @param grantRequest the grant request @@ -280,6 +303,7 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient headersConverter) { Assert.notNull(headersConverter, "headersConverter cannot be null"); this.headersConverter = headersConverter; + this.requestEntityConverter = this::populateRequest; } /** @@ -307,6 +331,7 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient> parametersConverter) { Assert.notNull(parametersConverter, "parametersConverter cannot be null"); this.parametersConverter = parametersConverter; + this.requestEntityConverter = this::populateRequest; } /** @@ -357,6 +383,7 @@ public abstract class AbstractWebClientReactiveOAuth2AccessTokenResponseClient + implements Converter> { + + private final Converter> delegate; + + ClientAuthenticationMethodValidatingRequestEntityConverter(Converter> delegate) { + this.delegate = delegate; + } + + @Override + public RequestEntity convert(T grantRequest) { + ClientRegistration clientRegistration = grantRequest.getClientRegistration(); + ClientAuthenticationMethod clientAuthenticationMethod = clientRegistration.getClientAuthenticationMethod(); + String registrationId = clientRegistration.getRegistrationId(); + boolean supportedClientAuthenticationMethod = clientAuthenticationMethod.equals(ClientAuthenticationMethod.NONE) + || clientAuthenticationMethod.equals(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) + || clientAuthenticationMethod.equals(ClientAuthenticationMethod.CLIENT_SECRET_POST); + Assert.isTrue(supportedClientAuthenticationMethod, () -> String.format( + "This class supports `client_secret_basic`, `client_secret_post`, and `none` by default. Client [%s] is using [%s] instead. Please use a supported client authentication method, or use `setRequestEntityConverter` to supply an instance that supports [%s].", + registrationId, clientAuthenticationMethod, clientAuthenticationMethod)); + return this.delegate.convert(grantRequest); + } + +} diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClient.java index d2b7587f90..179e564599 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClient.java @@ -58,7 +58,8 @@ public final class DefaultAuthorizationCodeTokenResponseClient private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; - private Converter> requestEntityConverter = new OAuth2AuthorizationCodeGrantRequestEntityConverter(); + private Converter> requestEntityConverter = new ClientAuthenticationMethodValidatingRequestEntityConverter<>( + new OAuth2AuthorizationCodeGrantRequestEntityConverter()); private RestOperations restOperations; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClient.java index a1ee225a94..71f80977f5 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClient.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,7 +58,8 @@ public final class DefaultClientCredentialsTokenResponseClient private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; - private Converter> requestEntityConverter = new OAuth2ClientCredentialsGrantRequestEntityConverter(); + private Converter> requestEntityConverter = new ClientAuthenticationMethodValidatingRequestEntityConverter<>( + new OAuth2ClientCredentialsGrantRequestEntityConverter()); private RestOperations restOperations; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultJwtBearerTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultJwtBearerTokenResponseClient.java index feae305eda..fa145da534 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultJwtBearerTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultJwtBearerTokenResponseClient.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +56,8 @@ public final class DefaultJwtBearerTokenResponseClient private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; - private Converter> requestEntityConverter = new JwtBearerGrantRequestEntityConverter(); + private Converter> requestEntityConverter = new ClientAuthenticationMethodValidatingRequestEntityConverter<>( + new JwtBearerGrantRequestEntityConverter()); private RestOperations restOperations; diff --git a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClient.java b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClient.java index 8550d077c0..0cadede9b3 100644 --- a/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClient.java +++ b/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClient.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,7 +55,8 @@ public final class DefaultRefreshTokenTokenResponseClient private static final String INVALID_TOKEN_RESPONSE_ERROR_CODE = "invalid_token_response"; - private Converter> requestEntityConverter = new OAuth2RefreshTokenGrantRequestEntityConverter(); + private Converter> requestEntityConverter = new ClientAuthenticationMethodValidatingRequestEntityConverter<>( + new OAuth2RefreshTokenGrantRequestEntityConverter()); private RestOperations restOperations; diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClientTests.java index 10ef7a95ed..c12b28fcfd 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultAuthorizationCodeTokenResponseClientTests.java @@ -370,6 +370,28 @@ public class DefaultAuthorizationCodeTokenResponseClientTests { + "the OAuth 2.0 Access Token Response"); } + // gh-13144 + @Test + public void getTokenResponseWhenCustomClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(new ClientAuthenticationMethod("basic")).build(); + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest = authorizationCodeGrantRequest( + clientRegistration); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest)); + } + + // gh-13144 + @Test + public void getTokenResponseWhenUnsupportedClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT).build(); + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest = authorizationCodeGrantRequest( + clientRegistration); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest)); + } + private OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest(ClientRegistration clientRegistration) { OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() .clientId(clientRegistration.getClientId()).state("state-1234") diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClientTests.java index cbc39a4321..aa7c199404 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultClientCredentialsTokenResponseClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -379,6 +379,28 @@ public class DefaultClientCredentialsTokenResponseClientTests { "[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response"); } + // gh-13144 + @Test + public void getTokenResponseWhenCustomClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(new ClientAuthenticationMethod("basic")).build(); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + clientRegistration); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest)); + } + + // gh-13144 + @Test + public void getTokenResponseWhenUnsupportedClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT).build(); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + clientRegistration); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(clientCredentialsGrantRequest)); + } + private MockResponse jsonResponse(String json) { return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultJwtBearerTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultJwtBearerTokenResponseClientTests.java index 14c27c993e..28988301fd 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultJwtBearerTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultJwtBearerTokenResponseClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -243,6 +243,26 @@ public class DefaultJwtBearerTokenResponseClientTests { + "retrieve the OAuth 2.0 Access Token Response"); } + // gh-13144 + @Test + public void getTokenResponseWhenCustomClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(new ClientAuthenticationMethod("basic")).build(); + JwtBearerGrantRequest jwtBearerGrantRequest = new JwtBearerGrantRequest(clientRegistration, this.jwtAssertion); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(jwtBearerGrantRequest)); + } + + // gh-13144 + @Test + public void getTokenResponseWhenUnsupportedClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT).build(); + JwtBearerGrantRequest jwtBearerGrantRequest = new JwtBearerGrantRequest(clientRegistration, this.jwtAssertion); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(jwtBearerGrantRequest)); + } + private MockResponse jsonResponse(String json) { return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClientTests.java index be563fe3d2..1bef2b8578 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/DefaultRefreshTokenTokenResponseClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -313,6 +313,28 @@ public class DefaultRefreshTokenTokenResponseClientTests { + "retrieve the OAuth 2.0 Access Token Response"); } + // gh-13144 + @Test + public void getTokenResponseWhenCustomClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(new ClientAuthenticationMethod("basic")).build(); + OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(clientRegistration, + this.accessToken, this.refreshToken); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest)); + } + + // gh-13144 + @Test + public void getTokenResponseWhenUnsupportedClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT).build(); + OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(clientRegistration, + this.accessToken, this.refreshToken); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest)); + } + private MockResponse jsonResponse(String json) { return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(json); } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java index bdc682a269..e3f59024da 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveAuthorizationCodeTokenResponseClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -500,4 +500,26 @@ public class WebClientReactiveAuthorizationCodeTokenResponseClientTests { } + // gh-13144 + @Test + public void getTokenResponseWhenCustomClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(new ClientAuthenticationMethod("basic")).build(); + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest = authorizationCodeGrantRequest( + clientRegistration); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest).block()); + } + + // gh-13144 + @Test + public void getTokenResponseWhenUnsupportedClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT).build(); + OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest = authorizationCodeGrantRequest( + clientRegistration); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(authorizationCodeGrantRequest).block()); + } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java index 16933ab2ef..010ec7a6cd 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveClientCredentialsTokenResponseClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -448,4 +448,26 @@ public class WebClientReactiveClientCredentialsTokenResponseClientTests { } + // gh-13144 + @Test + public void getTokenResponseWhenCustomClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(new ClientAuthenticationMethod("basic")).build(); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + clientRegistration); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.client.getTokenResponse(clientCredentialsGrantRequest).block()); + } + + // gh-13144 + @Test + public void getTokenResponseWhenUnsupportedClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT).build(); + OAuth2ClientCredentialsGrantRequest clientCredentialsGrantRequest = new OAuth2ClientCredentialsGrantRequest( + clientRegistration); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.client.getTokenResponse(clientCredentialsGrantRequest).block()); + } + } diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClientTests.java index d221511cc3..2545985573 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveJwtBearerTokenResponseClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -367,6 +367,26 @@ public class WebClientReactiveJwtBearerTokenResponseClientTests { assertThat(response.getAccessToken().getScopes()).isEmpty(); } + // gh-13144 + @Test + public void getTokenResponseWhenCustomClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(new ClientAuthenticationMethod("basic")).build(); + JwtBearerGrantRequest jwtBearerGrantRequest = new JwtBearerGrantRequest(clientRegistration, this.jwtAssertion); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.client.getTokenResponse(jwtBearerGrantRequest).block()); + } + + // gh-13144 + @Test + public void getTokenResponseWhenUnsupportedClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistration + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT).build(); + JwtBearerGrantRequest jwtBearerGrantRequest = new JwtBearerGrantRequest(clientRegistration, this.jwtAssertion); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.client.getTokenResponse(jwtBearerGrantRequest).block()); + } + private void enqueueJson(String body) { MockResponse response = new MockResponse().setBody(body).setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); diff --git a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java index 4d2c945237..2b2401fb62 100644 --- a/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java +++ b/oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/endpoint/WebClientReactiveRefreshTokenTokenResponseClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -462,4 +462,26 @@ public class WebClientReactiveRefreshTokenTokenResponseClientTests { } + // gh-13144 + @Test + public void getTokenResponseWhenCustomClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistrationBuilder + .clientAuthenticationMethod(new ClientAuthenticationMethod("basic")).build(); + OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(clientRegistration, + this.accessToken, this.refreshToken); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()); + } + + // gh-13144 + @Test + public void getTokenResponseWhenUnsupportedClientAuthenticationMethodThenIllegalArgument() { + ClientRegistration clientRegistration = this.clientRegistrationBuilder + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT).build(); + OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(clientRegistration, + this.accessToken, this.refreshToken); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> this.tokenResponseClient.getTokenResponse(refreshTokenGrantRequest).block()); + } + }