X509 client certificate authentication triggers when client id is provided
Closes gh-1635
This commit is contained in:
@@ -240,10 +240,10 @@ public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Co
|
||||
List<AuthenticationConverter> authenticationConverters = new ArrayList<>();
|
||||
|
||||
authenticationConverters.add(new JwtClientAssertionAuthenticationConverter());
|
||||
authenticationConverters.add(new X509ClientCertificateAuthenticationConverter());
|
||||
authenticationConverters.add(new ClientSecretBasicAuthenticationConverter());
|
||||
authenticationConverters.add(new ClientSecretPostAuthenticationConverter());
|
||||
authenticationConverters.add(new PublicClientAuthenticationConverter());
|
||||
authenticationConverters.add(new X509ClientCertificateAuthenticationConverter());
|
||||
|
||||
return authenticationConverters;
|
||||
}
|
||||
|
||||
@@ -114,10 +114,10 @@ public final class OAuth2ClientAuthenticationFilter extends OncePerRequestFilter
|
||||
this.authenticationConverter = new DelegatingAuthenticationConverter(
|
||||
Arrays.asList(
|
||||
new JwtClientAssertionAuthenticationConverter(),
|
||||
new X509ClientCertificateAuthenticationConverter(),
|
||||
new ClientSecretBasicAuthenticationConverter(),
|
||||
new ClientSecretPostAuthenticationConverter(),
|
||||
new PublicClientAuthenticationConverter()));
|
||||
new PublicClientAuthenticationConverter(),
|
||||
new X509ClientCertificateAuthenticationConverter()));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,11 @@ public final class X509ClientCertificateAuthenticationConverter implements Authe
|
||||
|
||||
// client_id (REQUIRED)
|
||||
String clientId = parameters.getFirst(OAuth2ParameterNames.CLIENT_ID);
|
||||
if (!StringUtils.hasText(clientId) || parameters.get(OAuth2ParameterNames.CLIENT_ID).size() != 1) {
|
||||
if (!StringUtils.hasText(clientId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parameters.get(OAuth2ParameterNames.CLIENT_ID).size() != 1) {
|
||||
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
@@ -309,6 +309,28 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
verify(jwtCustomizer).customize(any());
|
||||
}
|
||||
|
||||
// gh-1635
|
||||
@Test
|
||||
public void requestWhenTokenRequestIncludesBasicClientCredentialsAndX509ClientCertificateThenTokenResponse()
|
||||
throws Exception {
|
||||
this.spring.register(AuthorizationServerConfiguration.class).autowire();
|
||||
|
||||
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
|
||||
this.registeredClientRepository.save(registeredClient);
|
||||
|
||||
this.mvc
|
||||
.perform(post(DEFAULT_TOKEN_ENDPOINT_URI).with(x509(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE))
|
||||
.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
|
||||
.param(OAuth2ParameterNames.SCOPE, "scope1 scope2")
|
||||
.header(HttpHeaders.AUTHORIZATION,
|
||||
"Basic " + encodeBasicAuth(registeredClient.getClientId(), registeredClient.getClientSecret())))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.access_token").isNotEmpty())
|
||||
.andExpect(jsonPath("$.scope").value("scope1 scope2"));
|
||||
|
||||
verify(jwtCustomizer).customize(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenTokenEndpointCustomizedThenUsed() throws Exception {
|
||||
this.spring.register(AuthorizationServerConfigurationCustomTokenEndpoint.class).autowire();
|
||||
@@ -394,10 +416,10 @@ public class OAuth2ClientCredentialsGrantTests {
|
||||
List<AuthenticationConverter> authenticationConverters = authenticationConvertersCaptor.getValue();
|
||||
assertThat(authenticationConverters).allMatch((converter) -> converter == authenticationConverter
|
||||
|| converter instanceof JwtClientAssertionAuthenticationConverter
|
||||
|| converter instanceof X509ClientCertificateAuthenticationConverter
|
||||
|| converter instanceof ClientSecretBasicAuthenticationConverter
|
||||
|| converter instanceof ClientSecretPostAuthenticationConverter
|
||||
|| converter instanceof PublicClientAuthenticationConverter);
|
||||
|| converter instanceof PublicClientAuthenticationConverter
|
||||
|| converter instanceof X509ClientCertificateAuthenticationConverter);
|
||||
|
||||
verify(authenticationProvider).authenticate(eq(clientPrincipal));
|
||||
|
||||
|
||||
@@ -58,14 +58,12 @@ public class X509ClientCertificateAuthenticationConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertWhenMissingClientIdThenInvalidRequestError() {
|
||||
public void convertWhenMissingClientIdThenReturnNull() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setAttribute("jakarta.servlet.request.X509Certificate",
|
||||
TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE);
|
||||
assertThatThrownBy(() -> this.converter.convert(request)).isInstanceOf(OAuth2AuthenticationException.class)
|
||||
.extracting((ex) -> ((OAuth2AuthenticationException) ex).getError())
|
||||
.extracting("errorCode")
|
||||
.isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST);
|
||||
Authentication authentication = this.converter.convert(request);
|
||||
assertThat(authentication).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user