Skip to content

Commit 0ae0160

Browse files
committed
OAuth2ClientAuthenticationToken supports any type of credentials
Closes spring-projectsgh-382
1 parent e1b803c commit 0ae0160

24 files changed

+207
-161
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientAuthenticationProvider.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ public Authentication authenticate(Authentication authentication) throws Authent
121121
throwInvalidClient();
122122
}
123123

124-
return new OAuth2ClientAuthenticationToken(registeredClient);
124+
return new OAuth2ClientAuthenticationToken(registeredClient,
125+
clientAuthentication.getClientAuthenticationMethod(), clientAuthentication.getCredentials());
125126
}
126127

127128
@Override
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020 the original author or authors.
2+
* Copyright 2020-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,6 +15,9 @@
1515
*/
1616
package org.springframework.security.oauth2.server.authorization.authentication;
1717

18+
import java.util.Collections;
19+
import java.util.Map;
20+
1821
import org.springframework.lang.Nullable;
1922
import org.springframework.security.authentication.AbstractAuthenticationToken;
2023
import org.springframework.security.core.Authentication;
@@ -23,9 +26,6 @@
2326
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
2427
import org.springframework.util.Assert;
2528

26-
import java.util.Collections;
27-
import java.util.Map;
28-
2929
/**
3030
* An {@link Authentication} implementation used for OAuth 2.0 Client Authentication.
3131
*
@@ -39,94 +39,90 @@
3939
*/
4040
public class OAuth2ClientAuthenticationToken extends AbstractAuthenticationToken {
4141
private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
42-
private String clientId;
43-
private String clientSecret;
44-
private ClientAuthenticationMethod clientAuthenticationMethod;
45-
private Map<String, Object> additionalParameters;
46-
private RegisteredClient registeredClient;
42+
private final String clientId;
43+
private final RegisteredClient registeredClient;
44+
private final ClientAuthenticationMethod clientAuthenticationMethod;
45+
private final Object credentials;
46+
private final Map<String, Object> additionalParameters;
4747

4848
/**
4949
* Constructs an {@code OAuth2ClientAuthenticationToken} using the provided parameters.
5050
*
5151
* @param clientId the client identifier
52-
* @param clientSecret the client secret
5352
* @param clientAuthenticationMethod the authentication method used by the client
53+
* @param credentials the client credentials
5454
* @param additionalParameters the additional parameters
5555
*/
56-
public OAuth2ClientAuthenticationToken(String clientId, String clientSecret,
57-
ClientAuthenticationMethod clientAuthenticationMethod,
58-
@Nullable Map<String, Object> additionalParameters) {
59-
this(clientId, additionalParameters);
60-
Assert.hasText(clientSecret, "clientSecret cannot be empty");
61-
Assert.notNull(clientAuthenticationMethod, "clientAuthenticationMethod cannot be null");
62-
this.clientSecret = clientSecret;
63-
this.clientAuthenticationMethod = clientAuthenticationMethod;
64-
}
65-
66-
/**
67-
* Constructs an {@code OAuth2ClientAuthenticationToken} using the provided parameters.
68-
*
69-
* @param clientId the client identifier
70-
* @param additionalParameters the additional parameters
71-
*/
72-
public OAuth2ClientAuthenticationToken(String clientId,
73-
@Nullable Map<String, Object> additionalParameters) {
56+
public OAuth2ClientAuthenticationToken(String clientId, ClientAuthenticationMethod clientAuthenticationMethod,
57+
@Nullable Object credentials, @Nullable Map<String, Object> additionalParameters) {
7458
super(Collections.emptyList());
7559
Assert.hasText(clientId, "clientId cannot be empty");
60+
Assert.notNull(clientAuthenticationMethod, "clientAuthenticationMethod cannot be null");
7661
this.clientId = clientId;
77-
this.additionalParameters = additionalParameters != null ?
78-
Collections.unmodifiableMap(additionalParameters) : null;
79-
this.clientAuthenticationMethod = ClientAuthenticationMethod.NONE;
62+
this.registeredClient = null;
63+
this.clientAuthenticationMethod = clientAuthenticationMethod;
64+
this.credentials = credentials;
65+
this.additionalParameters = Collections.unmodifiableMap(
66+
additionalParameters != null ? additionalParameters : Collections.emptyMap());
8067
}
8168

8269
/**
8370
* Constructs an {@code OAuth2ClientAuthenticationToken} using the provided parameters.
8471
*
85-
* @param registeredClient the registered client
72+
* @param registeredClient the authenticated registered client
73+
* @param clientAuthenticationMethod the authentication method used by the client
74+
* @param credentials the client credentials
8675
*/
87-
public OAuth2ClientAuthenticationToken(RegisteredClient registeredClient) {
76+
public OAuth2ClientAuthenticationToken(RegisteredClient registeredClient, ClientAuthenticationMethod clientAuthenticationMethod,
77+
@Nullable Object credentials) {
8878
super(Collections.emptyList());
8979
Assert.notNull(registeredClient, "registeredClient cannot be null");
80+
Assert.notNull(clientAuthenticationMethod, "clientAuthenticationMethod cannot be null");
81+
this.clientId = registeredClient.getClientId();
9082
this.registeredClient = registeredClient;
83+
this.clientAuthenticationMethod = clientAuthenticationMethod;
84+
this.credentials = credentials;
85+
this.additionalParameters = Collections.unmodifiableMap(Collections.emptyMap());
9186
setAuthenticated(true);
9287
}
9388

9489
@Override
9590
public Object getPrincipal() {
96-
return this.registeredClient != null ?
97-
this.registeredClient.getClientId() :
98-
this.clientId;
91+
return this.clientId;
9992
}
10093

94+
@Nullable
10195
@Override
10296
public Object getCredentials() {
103-
return this.clientSecret;
97+
return this.credentials;
10498
}
10599

106100
/**
107-
* Returns the additional parameters
101+
* Returns the authenticated {@link RegisteredClient registered client}, or {@code null} if not authenticated.
108102
*
109-
* @return the additional parameters
103+
* @return the authenticated {@link RegisteredClient}, or {@code null} if not authenticated
110104
*/
111-
public @Nullable Map<String, Object> getAdditionalParameters() {
112-
return this.additionalParameters;
105+
@Nullable
106+
public RegisteredClient getRegisteredClient() {
107+
return this.registeredClient;
113108
}
114109

115110
/**
116-
* Returns the {@link RegisteredClient registered client}.
111+
* Returns the {@link ClientAuthenticationMethod authentication method} used by the client.
117112
*
118-
* @return the {@link RegisteredClient}
113+
* @return the {@link ClientAuthenticationMethod} used by the client
119114
*/
120-
public @Nullable RegisteredClient getRegisteredClient() {
121-
return this.registeredClient;
115+
public ClientAuthenticationMethod getClientAuthenticationMethod() {
116+
return this.clientAuthenticationMethod;
122117
}
123118

124119
/**
125-
* Returns the {@link ClientAuthenticationMethod client authentication method}.
120+
* Returns the additional parameters.
126121
*
127-
* @return the {@link ClientAuthenticationMethod}
122+
* @return the additional parameters
128123
*/
129-
public @Nullable ClientAuthenticationMethod getClientAuthenticationMethod() {
130-
return this.clientAuthenticationMethod;
124+
public Map<String, Object> getAdditionalParameters() {
125+
return this.additionalParameters;
131126
}
127+
132128
}

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/ClientSecretBasicAuthenticationConverter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public Authentication convert(HttpServletRequest request) {
8989
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST), ex);
9090
}
9191

92-
return new OAuth2ClientAuthenticationToken(clientID, clientSecret, ClientAuthenticationMethod.CLIENT_SECRET_BASIC,
92+
return new OAuth2ClientAuthenticationToken(clientID, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, clientSecret,
9393
extractAdditionalParameters(request));
9494
}
9595

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/ClientSecretPostAuthenticationConverter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public Authentication convert(HttpServletRequest request) {
7070
throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST));
7171
}
7272

73-
return new OAuth2ClientAuthenticationToken(clientId, clientSecret, ClientAuthenticationMethod.CLIENT_SECRET_POST,
73+
return new OAuth2ClientAuthenticationToken(clientId, ClientAuthenticationMethod.CLIENT_SECRET_POST, clientSecret,
7474
extractAdditionalParameters(request));
7575
}
7676

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/PublicClientAuthenticationConverter.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import javax.servlet.http.HttpServletRequest;
2121

2222
import org.springframework.security.core.Authentication;
23+
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
2324
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
2425
import org.springframework.security.oauth2.core.OAuth2Error;
2526
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
@@ -66,7 +67,7 @@ public Authentication convert(HttpServletRequest request) {
6667

6768
parameters.remove(OAuth2ParameterNames.CLIENT_ID);
6869

69-
return new OAuth2ClientAuthenticationToken(
70-
clientId, new HashMap<>(parameters.toSingleValueMap()));
70+
return new OAuth2ClientAuthenticationToken(clientId, ClientAuthenticationMethod.NONE, null,
71+
new HashMap<>(parameters.toSingleValueMap()));
7172
}
7273
}

oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2ClientCredentialsGrantTests.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
5757
import org.springframework.security.crypto.password.PasswordEncoder;
5858
import org.springframework.security.oauth2.core.AuthorizationGrantType;
59+
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
5960
import org.springframework.security.oauth2.core.OAuth2AccessToken;
6061
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
6162
import org.springframework.security.oauth2.jose.TestJwks;
@@ -211,7 +212,8 @@ public void requestWhenTokenEndpointCustomizedThenUsed() throws Exception {
211212
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
212213
this.registeredClientRepository.save(registeredClient);
213214

214-
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
215+
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
216+
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
215217
OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication =
216218
new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null);
217219
when(authenticationConverter.convert(any())).thenReturn(clientCredentialsAuthentication);
@@ -242,7 +244,8 @@ public void requestWhenClientAuthenticationCustomizedThenUsed() throws Exception
242244
RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build();
243245
this.registeredClientRepository.save(registeredClient);
244246

245-
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
247+
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
248+
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
246249
when(authenticationConverter.convert(any())).thenReturn(clientPrincipal);
247250
when(authenticationProvider.supports(eq(OAuth2ClientAuthenticationToken.class))).thenReturn(true);
248251
when(authenticationProvider.authenticate(any())).thenReturn(clientPrincipal);

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/JwtEncodingContextTests.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.springframework.security.authentication.TestingAuthenticationToken;
2121
import org.springframework.security.core.Authentication;
2222
import org.springframework.security.oauth2.core.AuthorizationGrantType;
23+
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
2324
import org.springframework.security.oauth2.core.OAuth2TokenType;
2425
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
2526
import org.springframework.security.oauth2.jwt.JoseHeader;
@@ -83,7 +84,8 @@ public void buildWhenAllValuesProvidedThenAllValuesAreSet() {
8384
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
8485
TestingAuthenticationToken principal = new TestingAuthenticationToken("principal", "password");
8586
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization().build();
86-
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient);
87+
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
88+
registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret());
8789
OAuth2AuthorizationRequest authorizationRequest = authorization.getAttribute(
8890
OAuth2AuthorizationRequest.class.getName());
8991
OAuth2AuthorizationCodeAuthenticationToken authorizationGrant =

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AccessTokenAuthenticationTokenTests.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
package org.springframework.security.oauth2.server.authorization.authentication;
1717

1818
import org.junit.Test;
19+
20+
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
1921
import org.springframework.security.oauth2.core.OAuth2AccessToken;
2022
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
2123
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
@@ -36,8 +38,8 @@
3638
*/
3739
public class OAuth2AccessTokenAuthenticationTokenTests {
3840
private RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
39-
private OAuth2ClientAuthenticationToken clientPrincipal =
40-
new OAuth2ClientAuthenticationToken(this.registeredClient);
41+
private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(
42+
this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret());
4143
private OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
4244
"access-token", Instant.now(), Instant.now().plusSeconds(300));
4345
private OAuth2RefreshToken refreshToken = new OAuth2RefreshToken(

0 commit comments

Comments
 (0)