Skip to content

Commit f9498d3

Browse files
committed
PKCE cannot be true and AuthorizationGrantType != AUTHORIZATION_CODE
PKCE is only valid for AuthorizationGrantType.AUTHORIZATION_CODE so the code should validate this. Issue gh-16382
1 parent ab629cc commit f9498d3

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java

+6
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,12 @@ private void validateAuthorizationGrantTypes() {
711711
"AuthorizationGrantType: %s does not match the pre-defined constant %s and won't match a valid OAuth2AuthorizedClientProvider",
712712
this.authorizationGrantType, authorizationGrantType));
713713
}
714+
if (!AuthorizationGrantType.AUTHORIZATION_CODE.equals(this.authorizationGrantType)
715+
&& this.clientSettings.isRequireProofKey()) {
716+
throw new IllegalStateException(
717+
"clientSettings.isRequireProofKey=true is only valid with authorizationGrantType=AUTHORIZATION_CODE. Got authorizationGrantType="
718+
+ this.authorizationGrantType);
719+
}
714720
}
715721
}
716722

oauth2/oauth2-client/src/test/java/org/springframework/security/oauth2/client/registration/ClientRegistrationTests.java

+62
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,28 @@
1616

1717
package org.springframework.security.oauth2.client.registration;
1818

19+
import java.lang.reflect.Field;
20+
import java.lang.reflect.Modifier;
21+
import java.util.Arrays;
1922
import java.util.Collections;
2023
import java.util.LinkedHashMap;
24+
import java.util.List;
2125
import java.util.Map;
2226
import java.util.Set;
2327
import java.util.stream.Collectors;
2428
import java.util.stream.Stream;
2529

2630
import org.junit.jupiter.api.Test;
31+
import org.junit.jupiter.params.ParameterizedTest;
32+
import org.junit.jupiter.params.provider.MethodSource;
2733

2834
import org.springframework.security.oauth2.core.AuthenticationMethod;
2935
import org.springframework.security.oauth2.core.AuthorizationGrantType;
3036
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
3137

3238
import static org.assertj.core.api.Assertions.assertThat;
3339
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
40+
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
3441

3542
/**
3643
* Tests for {@link ClientRegistration}.
@@ -776,4 +783,59 @@ void buildWhenDefaultClientSettingsThenDefaulted() {
776783
assertThat(clientRegistration.getClientSettings().isRequireProofKey()).isFalse();
777784
}
778785

786+
// gh-16382
787+
@Test
788+
void buildWhenNewAuthorizationCodeAndPkceThenBuilds() {
789+
ClientSettings pkceEnabled = ClientSettings.builder().requireProofKey(true).build();
790+
ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(REGISTRATION_ID)
791+
.clientId(CLIENT_ID)
792+
.clientSettings(pkceEnabled)
793+
.authorizationGrantType(new AuthorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()))
794+
.redirectUri(REDIRECT_URI)
795+
.authorizationUri(AUTHORIZATION_URI)
796+
.tokenUri(TOKEN_URI)
797+
.build();
798+
799+
// proof key should be false for passivity
800+
assertThat(clientRegistration.getClientSettings().isRequireProofKey()).isTrue();
801+
}
802+
803+
@ParameterizedTest
804+
@MethodSource("invalidPkceGrantTypes")
805+
void buildWhenInvalidGrantTypeForPkceThenException(AuthorizationGrantType invalidGrantType) {
806+
ClientSettings pkceEnabled = ClientSettings.builder().requireProofKey(true).build();
807+
ClientRegistration.Builder builder = ClientRegistration.withRegistrationId(REGISTRATION_ID)
808+
.clientId(CLIENT_ID)
809+
.clientSettings(pkceEnabled)
810+
.authorizationGrantType(invalidGrantType)
811+
.redirectUri(REDIRECT_URI)
812+
.authorizationUri(AUTHORIZATION_URI)
813+
.tokenUri(TOKEN_URI);
814+
815+
assertThatIllegalStateException().describedAs(
816+
"clientSettings.isRequireProofKey=true is only valid with authorizationGrantType=AUTHORIZATION_CODE. Got authorizationGrantType={}",
817+
invalidGrantType)
818+
.isThrownBy(builder::build);
819+
}
820+
821+
static List<AuthorizationGrantType> invalidPkceGrantTypes() {
822+
return Arrays.stream(AuthorizationGrantType.class.getFields())
823+
.filter((field) -> Modifier.isFinal(field.getModifiers())
824+
&& field.getType() == AuthorizationGrantType.class)
825+
.map((field) -> getStaticValue(field, AuthorizationGrantType.class))
826+
.filter((grantType) -> grantType != AuthorizationGrantType.AUTHORIZATION_CODE)
827+
// ensure works with .equals
828+
.map((grantType) -> new AuthorizationGrantType(grantType.getValue()))
829+
.collect(Collectors.toList());
830+
}
831+
832+
private static <T> T getStaticValue(Field field, Class<T> clazz) {
833+
try {
834+
return (T) field.get(null);
835+
}
836+
catch (IllegalAccessException ex) {
837+
throw new RuntimeException(ex);
838+
}
839+
}
840+
779841
}

0 commit comments

Comments
 (0)