Browse Source

Introduce base Authentication for authorization grant

Closes gh-216
Joe Grandja 4 years ago
parent
commit
218d49b134
15 changed files with 177 additions and 318 deletions
  1. 9 39
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationToken.java
  2. 91 0
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationGrantAuthenticationToken.java
  3. 8 24
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationToken.java
  4. 8 24
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationToken.java
  5. 3 2
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2TokenContext.java
  6. 0 70
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverter.java
  7. 26 24
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilter.java
  8. 4 4
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java
  9. 7 4
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationTokenTests.java
  10. 2 2
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProviderTests.java
  11. 8 4
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationTokenTests.java
  12. 2 2
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProviderTests.java
  13. 7 4
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationTokenTests.java
  14. 2 1
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/token/JwtEncodingContextTests.java
  15. 0 114
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverterTests.java

+ 9 - 39
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationToken.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 the original author or authors.
+ * Copyright 2020-2021 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.
@@ -15,15 +15,13 @@
  */
 package org.springframework.security.oauth2.server.authorization.authentication;
 
+import java.util.Map;
+
 import org.springframework.lang.Nullable;
-import org.springframework.security.authentication.AbstractAuthenticationToken;
 import org.springframework.security.core.Authentication;
-import org.springframework.security.oauth2.server.authorization.Version;
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
 import org.springframework.util.Assert;
 
-import java.util.Collections;
-import java.util.Map;
-
 /**
  * An {@link Authentication} implementation used for the OAuth 2.0 Authorization Code Grant.
  *
@@ -31,16 +29,12 @@ import java.util.Map;
  * @author Madhu Bhat
  * @author Daniel Garnier-Moiroux
  * @since 0.0.1
- * @see AbstractAuthenticationToken
+ * @see OAuth2AuthorizationGrantAuthenticationToken
  * @see OAuth2AuthorizationCodeAuthenticationProvider
- * @see OAuth2ClientAuthenticationToken
  */
-public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenticationToken {
-	private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
+public class OAuth2AuthorizationCodeAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken {
 	private final String code;
-	private final Authentication clientPrincipal;
 	private final String redirectUri;
-	private final Map<String, Object> additionalParameters;
 
 	/**
 	 * Constructs an {@code OAuth2AuthorizationCodeAuthenticationToken} using the provided parameters.
@@ -52,26 +46,10 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti
 	 */
 	public OAuth2AuthorizationCodeAuthenticationToken(String code, Authentication clientPrincipal,
 			@Nullable String redirectUri, @Nullable Map<String, Object> additionalParameters) {
-		super(Collections.emptyList());
+		super(AuthorizationGrantType.AUTHORIZATION_CODE, clientPrincipal, additionalParameters);
 		Assert.hasText(code, "code cannot be empty");
-		Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
 		this.code = code;
-		this.clientPrincipal = clientPrincipal;
 		this.redirectUri = redirectUri;
-		this.additionalParameters = Collections.unmodifiableMap(
-				additionalParameters != null ?
-						additionalParameters :
-						Collections.emptyMap());
-	}
-
-	@Override
-	public Object getPrincipal() {
-		return this.clientPrincipal;
-	}
-
-	@Override
-	public Object getCredentials() {
-		return "";
 	}
 
 	/**
@@ -88,16 +66,8 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti
 	 *
 	 * @return the redirect uri
 	 */
-	public @Nullable String getRedirectUri() {
+	@Nullable
+	public String getRedirectUri() {
 		return this.redirectUri;
 	}
-
-	/**
-	 * Returns the additional parameters
-	 *
-	 * @return the additional parameters
-	 */
-	public Map<String, Object> getAdditionalParameters() {
-		return this.additionalParameters;
-	}
 }

+ 91 - 0
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationGrantAuthenticationToken.java

@@ -0,0 +1,91 @@
+/*
+ * Copyright 2020-2021 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.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.security.oauth2.server.authorization.authentication;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.springframework.lang.Nullable;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
+import org.springframework.security.oauth2.server.authorization.Version;
+import org.springframework.util.Assert;
+
+/**
+ * Base implementation of an {@link Authentication} representing an OAuth 2.0 Authorization Grant.
+ *
+ * @author Joe Grandja
+ * @since 0.1.0
+ * @see AbstractAuthenticationToken
+ * @see AuthorizationGrantType
+ * @see OAuth2ClientAuthenticationToken
+ * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-1.3">Section 1.3 Authorization Grant</a>
+ */
+public class OAuth2AuthorizationGrantAuthenticationToken extends AbstractAuthenticationToken {
+	private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
+	private final AuthorizationGrantType authorizationGrantType;
+	private final Authentication clientPrincipal;
+	private final Map<String, Object> additionalParameters;
+
+	/**
+	 * Sub-class constructor.
+	 *
+	 * @param authorizationGrantType the authorization grant type
+	 * @param clientPrincipal the authenticated client principal
+	 * @param additionalParameters the additional parameters
+	 */
+	protected OAuth2AuthorizationGrantAuthenticationToken(AuthorizationGrantType authorizationGrantType,
+			Authentication clientPrincipal, @Nullable Map<String, Object> additionalParameters) {
+		super(Collections.emptyList());
+		Assert.notNull(authorizationGrantType, "authorizationGrantType cannot be null");
+		Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
+		this.authorizationGrantType = authorizationGrantType;
+		this.clientPrincipal = clientPrincipal;
+		this.additionalParameters = Collections.unmodifiableMap(
+				additionalParameters != null ?
+						additionalParameters :
+						Collections.emptyMap());
+	}
+
+	/**
+	 * Returns the authorization grant type.
+	 *
+	 * @return the authorization grant type
+	 */
+	public AuthorizationGrantType getGrantType() {
+		return this.authorizationGrantType;
+	}
+
+	@Override
+	public Object getPrincipal() {
+		return this.clientPrincipal;
+	}
+
+	@Override
+	public Object getCredentials() {
+		return "";
+	}
+
+	/**
+	 * Returns the additional parameters.
+	 *
+	 * @return the additional parameters
+	 */
+	public Map<String, Object> getAdditionalParameters() {
+		return this.additionalParameters;
+	}
+}

+ 8 - 24
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationToken.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 the original author or authors.
+ * Copyright 2020-2021 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.
@@ -15,27 +15,23 @@
  */
 package org.springframework.security.oauth2.server.authorization.authentication;
 
-import org.springframework.security.authentication.AbstractAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.oauth2.server.authorization.Version;
-import org.springframework.util.Assert;
-
 import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
+import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
+import org.springframework.util.Assert;
+
 /**
  * An {@link Authentication} implementation used for the OAuth 2.0 Client Credentials Grant.
  *
  * @author Alexey Nesterov
  * @since 0.0.1
- * @see AbstractAuthenticationToken
+ * @see OAuth2AuthorizationGrantAuthenticationToken
  * @see OAuth2ClientCredentialsAuthenticationProvider
- * @see OAuth2ClientAuthenticationToken
  */
-public class OAuth2ClientCredentialsAuthenticationToken extends AbstractAuthenticationToken {
-	private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
-	private final Authentication clientPrincipal;
+public class OAuth2ClientCredentialsAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken {
 	private final Set<String> scopes;
 
 	/**
@@ -54,23 +50,11 @@ public class OAuth2ClientCredentialsAuthenticationToken extends AbstractAuthenti
 	 * @param scopes the requested scope(s)
 	 */
 	public OAuth2ClientCredentialsAuthenticationToken(Authentication clientPrincipal, Set<String> scopes) {
-		super(Collections.emptyList());
-		Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
+		super(AuthorizationGrantType.CLIENT_CREDENTIALS, clientPrincipal, null);
 		Assert.notNull(scopes, "scopes cannot be null");
-		this.clientPrincipal = clientPrincipal;
 		this.scopes = Collections.unmodifiableSet(new LinkedHashSet<>(scopes));
 	}
 
-	@Override
-	public Object getPrincipal() {
-		return this.clientPrincipal;
-	}
-
-	@Override
-	public Object getCredentials() {
-		return "";
-	}
-
 	/**
 	 * Returns the requested scope(s).
 	 *

+ 8 - 24
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationToken.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 the original author or authors.
+ * Copyright 2020-2021 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.
@@ -15,27 +15,23 @@
  */
 package org.springframework.security.oauth2.server.authorization.authentication;
 
-import org.springframework.security.authentication.AbstractAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.oauth2.server.authorization.Version;
-import org.springframework.util.Assert;
-
 import java.util.Collections;
 import java.util.Set;
 
+import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
+import org.springframework.util.Assert;
+
 /**
  * An {@link Authentication} implementation used for the OAuth 2.0 Refresh Token Grant.
  *
  * @author Alexey Nesterov
  * @since 0.0.3
- * @see AbstractAuthenticationToken
+ * @see OAuth2AuthorizationGrantAuthenticationToken
  * @see OAuth2RefreshTokenAuthenticationProvider
- * @see OAuth2ClientAuthenticationToken
  */
-public class OAuth2RefreshTokenAuthenticationToken extends AbstractAuthenticationToken {
-	private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
+public class OAuth2RefreshTokenAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken {
 	private final String refreshToken;
-	private final Authentication clientPrincipal;
 	private final Set<String> scopes;
 
 	/**
@@ -57,25 +53,13 @@ public class OAuth2RefreshTokenAuthenticationToken extends AbstractAuthenticatio
 	 */
 	public OAuth2RefreshTokenAuthenticationToken(String refreshToken, Authentication clientPrincipal,
 			Set<String> scopes) {
-		super(Collections.emptySet());
+		super(AuthorizationGrantType.REFRESH_TOKEN, clientPrincipal, null);
 		Assert.hasText(refreshToken, "refreshToken cannot be empty");
-		Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
 		Assert.notNull(scopes, "scopes cannot be null");
 		this.refreshToken = refreshToken;
-		this.clientPrincipal = clientPrincipal;
 		this.scopes = scopes;
 	}
 
-	@Override
-	public Object getPrincipal() {
-		return this.clientPrincipal;
-	}
-
-	@Override
-	public Object getCredentials() {
-		return "";
-	}
-
 	/**
 	 * Returns the refresh token.
 	 *

+ 3 - 2
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2TokenContext.java

@@ -25,6 +25,7 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
 import org.springframework.security.oauth2.core.context.Context;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.TokenType;
+import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationGrantAuthenticationToken;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 import org.springframework.util.Assert;
 
@@ -56,7 +57,7 @@ public interface OAuth2TokenContext extends Context {
 		return get(AuthorizationGrantType.class);
 	}
 
-	default <T extends Authentication> T getAuthorizationGrant() {
+	default <T extends OAuth2AuthorizationGrantAuthenticationToken> T getAuthorizationGrant() {
 		return get(AbstractBuilder.AUTHORIZATION_GRANT_AUTHENTICATION_KEY);
 	}
 
@@ -87,7 +88,7 @@ public interface OAuth2TokenContext extends Context {
 			return put(AuthorizationGrantType.class, authorizationGrantType);
 		}
 
-		public B authorizationGrant(Authentication authorizationGrant) {
+		public B authorizationGrant(OAuth2AuthorizationGrantAuthenticationToken authorizationGrant) {
 			return put(AUTHORIZATION_GRANT_AUTHENTICATION_KEY, authorizationGrant);
 		}
 

+ 0 - 70
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverter.java

@@ -1,70 +0,0 @@
-/*
- * Copyright 2020 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.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.server.authorization.web;
-
-import org.springframework.core.convert.converter.Converter;
-import org.springframework.lang.Nullable;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.oauth2.core.AuthorizationGrantType;
-import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A {@link Converter} that selects (and delegates) to one of the internal {@code Map} of {@link Converter}'s
- * using the {@link OAuth2ParameterNames#GRANT_TYPE} request parameter.
- *
- * @author Alexey Nesterov
- * @since 0.0.1
- */
-public final class DelegatingAuthorizationGrantAuthenticationConverter implements Converter<HttpServletRequest, Authentication> {
-	private final Map<AuthorizationGrantType, Converter<HttpServletRequest, Authentication>> converters;
-
-	/**
-	 * Constructs a {@code DelegatingAuthorizationGrantAuthenticationConverter} using the provided parameters.
-	 *
-	 * @param converters a {@code Map} of {@link Converter}(s)
-	 */
-	public DelegatingAuthorizationGrantAuthenticationConverter(
-			Map<AuthorizationGrantType, Converter<HttpServletRequest, Authentication>> converters) {
-		Assert.notEmpty(converters, "converters cannot be empty");
-		this.converters = Collections.unmodifiableMap(new HashMap<>(converters));
-	}
-
-	@Nullable
-	@Override
-	public Authentication convert(HttpServletRequest request) {
-		Assert.notNull(request, "request cannot be null");
-
-		String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
-		if (StringUtils.isEmpty(grantType)) {
-			return null;
-		}
-
-		Converter<HttpServletRequest, Authentication> converter =
-				this.converters.get(new AuthorizationGrantType(grantType));
-		if (converter == null) {
-			return null;
-		}
-
-		return converter.convert(request);
-	}
-}

+ 26 - 24
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilter.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 the original author or authors.
+ * Copyright 2020-2021 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.
@@ -15,7 +15,21 @@
  */
 package org.springframework.security.oauth2.server.authorization.web;
 
-import org.springframework.core.convert.converter.Converter;
+import java.io.IOException;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.converter.HttpMessageConverter;
@@ -40,6 +54,7 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
 import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken;
 import org.springframework.security.oauth2.server.authorization.authentication.OAuth2RefreshTokenAuthenticationProvider;
 import org.springframework.security.oauth2.server.authorization.authentication.OAuth2RefreshTokenAuthenticationToken;
+import org.springframework.security.web.authentication.AuthenticationConverter;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
 import org.springframework.util.Assert;
@@ -48,19 +63,6 @@ import org.springframework.util.MultiValueMap;
 import org.springframework.util.StringUtils;
 import org.springframework.web.filter.OncePerRequestFilter;
 
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.time.temporal.ChronoUnit;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
 /**
  * A {@code Filter} for the OAuth 2.0 Token endpoint,
  * which handles the processing of an OAuth 2.0 Authorization Grant.
@@ -98,7 +100,7 @@ public class OAuth2TokenEndpointFilter extends OncePerRequestFilter {
 
 	private final AuthenticationManager authenticationManager;
 	private final RequestMatcher tokenEndpointMatcher;
-	private final Converter<HttpServletRequest, Authentication> authorizationGrantAuthenticationConverter;
+	private final AuthenticationConverter authorizationGrantAuthenticationConverter;
 	private final HttpMessageConverter<OAuth2AccessTokenResponse> accessTokenHttpResponseConverter =
 			new OAuth2AccessTokenResponseHttpMessageConverter();
 	private final HttpMessageConverter<OAuth2Error> errorHttpResponseConverter =
@@ -124,11 +126,11 @@ public class OAuth2TokenEndpointFilter extends OncePerRequestFilter {
 		Assert.hasText(tokenEndpointUri, "tokenEndpointUri cannot be empty");
 		this.authenticationManager = authenticationManager;
 		this.tokenEndpointMatcher = new AntPathRequestMatcher(tokenEndpointUri, HttpMethod.POST.name());
-		Map<AuthorizationGrantType, Converter<HttpServletRequest, Authentication>> converters = new HashMap<>();
-		converters.put(AuthorizationGrantType.AUTHORIZATION_CODE, new AuthorizationCodeAuthenticationConverter());
-		converters.put(AuthorizationGrantType.REFRESH_TOKEN, new RefreshTokenAuthenticationConverter());
-		converters.put(AuthorizationGrantType.CLIENT_CREDENTIALS, new ClientCredentialsAuthenticationConverter());
-		this.authorizationGrantAuthenticationConverter = new DelegatingAuthorizationGrantAuthenticationConverter(converters);
+		List<AuthenticationConverter> converters = new ArrayList<>();
+		converters.add(new AuthorizationCodeAuthenticationConverter());
+		converters.add(new RefreshTokenAuthenticationConverter());
+		converters.add(new ClientCredentialsAuthenticationConverter());
+		this.authorizationGrantAuthenticationConverter = new DelegatingAuthenticationConverter(converters);
 	}
 
 	@Override
@@ -198,7 +200,7 @@ public class OAuth2TokenEndpointFilter extends OncePerRequestFilter {
 		throw new OAuth2AuthenticationException(error);
 	}
 
-	private static class AuthorizationCodeAuthenticationConverter implements Converter<HttpServletRequest, Authentication> {
+	private static class AuthorizationCodeAuthenticationConverter implements AuthenticationConverter {
 
 		@Override
 		public Authentication convert(HttpServletRequest request) {
@@ -240,7 +242,7 @@ public class OAuth2TokenEndpointFilter extends OncePerRequestFilter {
 		}
 	}
 
-	private static class RefreshTokenAuthenticationConverter implements Converter<HttpServletRequest, Authentication> {
+	private static class RefreshTokenAuthenticationConverter implements AuthenticationConverter {
 
 		@Override
 		public Authentication convert(HttpServletRequest request) {
@@ -277,7 +279,7 @@ public class OAuth2TokenEndpointFilter extends OncePerRequestFilter {
 		}
 	}
 
-	private static class ClientCredentialsAuthenticationConverter implements Converter<HttpServletRequest, Authentication> {
+	private static class ClientCredentialsAuthenticationConverter implements AuthenticationConverter {
 
 		@Override
 		public Authentication convert(HttpServletRequest request) {

+ 4 - 4
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java

@@ -40,7 +40,6 @@ import org.springframework.security.oauth2.jwt.JoseHeaderNames;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtClaimsSet;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationAttributeNames;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
@@ -48,6 +47,7 @@ import org.springframework.security.oauth2.server.authorization.TestOAuth2Author
 import org.springframework.security.oauth2.server.authorization.TokenType;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
+import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
 import org.springframework.security.oauth2.server.authorization.token.OAuth2AuthorizationCode;
 import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
 import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenMetadata;
@@ -247,7 +247,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		assertThat(jwtEncodingContext.getAuthorization()).isEqualTo(authorization);
 		assertThat(jwtEncodingContext.getTokenType()).isEqualTo(TokenType.ACCESS_TOKEN);
 		assertThat(jwtEncodingContext.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
-		assertThat(jwtEncodingContext.<Authentication>getAuthorizationGrant()).isEqualTo(authentication);
+		assertThat(jwtEncodingContext.<OAuth2AuthorizationGrantAuthenticationToken>getAuthorizationGrant()).isEqualTo(authentication);
 		assertThat(jwtEncodingContext.getHeaders()).isNotNull();
 		assertThat(jwtEncodingContext.getClaims()).isNotNull();
 
@@ -299,7 +299,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		assertThat(accessTokenContext.getAuthorization()).isEqualTo(authorization);
 		assertThat(accessTokenContext.getTokenType()).isEqualTo(TokenType.ACCESS_TOKEN);
 		assertThat(accessTokenContext.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
-		assertThat(accessTokenContext.<Authentication>getAuthorizationGrant()).isEqualTo(authentication);
+		assertThat(accessTokenContext.<OAuth2AuthorizationGrantAuthenticationToken>getAuthorizationGrant()).isEqualTo(authentication);
 		assertThat(accessTokenContext.getHeaders()).isNotNull();
 		assertThat(accessTokenContext.getClaims()).isNotNull();
 		// ID Token context
@@ -309,7 +309,7 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests {
 		assertThat(idTokenContext.getAuthorization()).isEqualTo(authorization);
 		assertThat(idTokenContext.getTokenType().getValue()).isEqualTo(OidcParameterNames.ID_TOKEN);
 		assertThat(idTokenContext.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
-		assertThat(idTokenContext.<Authentication>getAuthorizationGrant()).isEqualTo(authentication);
+		assertThat(idTokenContext.<OAuth2AuthorizationGrantAuthenticationToken>getAuthorizationGrant()).isEqualTo(authentication);
 		assertThat(idTokenContext.getHeaders()).isNotNull();
 		assertThat(idTokenContext.getClaims()).isNotNull();
 

+ 7 - 4
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationTokenTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 the original author or authors.
+ * Copyright 2020-2021 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.
@@ -15,12 +15,14 @@
  */
 package org.springframework.security.oauth2.server.authorization.authentication;
 
-import org.junit.Test;
-import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
-
 import java.util.Collections;
 import java.util.Map;
 
+import org.junit.Test;
+
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
+import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
+
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
@@ -55,6 +57,7 @@ public class OAuth2AuthorizationCodeAuthenticationTokenTests {
 	public void constructorWhenClientPrincipalProvidedThenCreated() {
 		OAuth2AuthorizationCodeAuthenticationToken authentication = new OAuth2AuthorizationCodeAuthenticationToken(
 				this.code, this.clientPrincipal, this.redirectUri, this.additionalParameters);
+		assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
 		assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
 		assertThat(authentication.getCredentials().toString()).isEmpty();
 		assertThat(authentication.getCode()).isEqualTo(this.code);

+ 2 - 2
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProviderTests.java

@@ -35,12 +35,12 @@ import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
 import org.springframework.security.oauth2.jwt.JoseHeaderNames;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
 import org.springframework.security.oauth2.server.authorization.TokenType;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
+import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
 import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -194,7 +194,7 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests {
 		assertThat(jwtEncodingContext.getAuthorization()).isNull();
 		assertThat(jwtEncodingContext.getTokenType()).isEqualTo(TokenType.ACCESS_TOKEN);
 		assertThat(jwtEncodingContext.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS);
-		assertThat(jwtEncodingContext.<Authentication>getAuthorizationGrant()).isEqualTo(authentication);
+		assertThat(jwtEncodingContext.<OAuth2AuthorizationGrantAuthenticationToken>getAuthorizationGrant()).isEqualTo(authentication);
 		assertThat(jwtEncodingContext.getHeaders()).isNotNull();
 		assertThat(jwtEncodingContext.getClaims()).isNotNull();
 

+ 8 - 4
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationTokenTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 the original author or authors.
+ * Copyright 2020-2021 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.
@@ -15,12 +15,14 @@
  */
 package org.springframework.security.oauth2.server.authorization.authentication;
 
-import org.junit.Test;
-import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
-
 import java.util.Collections;
 import java.util.Set;
 
+import org.junit.Test;
+
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
+import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
+
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
@@ -52,6 +54,7 @@ public class OAuth2ClientCredentialsAuthenticationTokenTests {
 		OAuth2ClientCredentialsAuthenticationToken authentication =
 				new OAuth2ClientCredentialsAuthenticationToken(this.clientPrincipal);
 
+		assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS);
 		assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
 		assertThat(authentication.getCredentials().toString()).isEmpty();
 		assertThat(authentication.getScopes()).isEmpty();
@@ -64,6 +67,7 @@ public class OAuth2ClientCredentialsAuthenticationTokenTests {
 		OAuth2ClientCredentialsAuthenticationToken authentication =
 				new OAuth2ClientCredentialsAuthenticationToken(this.clientPrincipal, expectedScopes);
 
+		assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.CLIENT_CREDENTIALS);
 		assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
 		assertThat(authentication.getCredentials().toString()).isEmpty();
 		assertThat(authentication.getScopes()).isEqualTo(expectedScopes);

+ 2 - 2
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProviderTests.java

@@ -38,7 +38,6 @@ import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
 import org.springframework.security.oauth2.jwt.JoseHeaderNames;
 import org.springframework.security.oauth2.jwt.Jwt;
 import org.springframework.security.oauth2.jwt.JwtEncoder;
-import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
 import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationAttributeNames;
 import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
@@ -46,6 +45,7 @@ import org.springframework.security.oauth2.server.authorization.TestOAuth2Author
 import org.springframework.security.oauth2.server.authorization.TokenType;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
+import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
 import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
 import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenMetadata;
 import org.springframework.security.oauth2.server.authorization.token.OAuth2Tokens;
@@ -139,7 +139,7 @@ public class OAuth2RefreshTokenAuthenticationProviderTests {
 		assertThat(jwtEncodingContext.getAuthorization()).isEqualTo(authorization);
 		assertThat(jwtEncodingContext.getTokenType()).isEqualTo(TokenType.ACCESS_TOKEN);
 		assertThat(jwtEncodingContext.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.REFRESH_TOKEN);
-		assertThat(jwtEncodingContext.<Authentication>getAuthorizationGrant()).isEqualTo(authentication);
+		assertThat(jwtEncodingContext.<OAuth2AuthorizationGrantAuthenticationToken>getAuthorizationGrant()).isEqualTo(authentication);
 		assertThat(jwtEncodingContext.getHeaders()).isNotNull();
 		assertThat(jwtEncodingContext.getClaims()).isNotNull();
 

+ 7 - 4
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationTokenTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 the original author or authors.
+ * Copyright 2020-2021 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.
@@ -15,13 +15,15 @@
  */
 package org.springframework.security.oauth2.server.authorization.authentication;
 
-import org.junit.Test;
-import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
-
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
 
+import org.junit.Test;
+
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
+import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
+
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
@@ -64,6 +66,7 @@ public class OAuth2RefreshTokenAuthenticationTokenTests {
 		Set<String> expectedScopes = new HashSet<>(Arrays.asList("scope-a", "scope-b"));
 		OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken(
 				"refresh-token", this.clientPrincipal, expectedScopes);
+		assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.REFRESH_TOKEN);
 		assertThat(authentication.getRefreshToken()).isEqualTo("refresh-token");
 		assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal);
 		assertThat(authentication.getCredentials().toString()).isEmpty();

+ 2 - 1
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/token/JwtEncodingContextTests.java

@@ -30,6 +30,7 @@ import org.springframework.security.oauth2.server.authorization.OAuth2Authorizat
 import org.springframework.security.oauth2.server.authorization.TestOAuth2Authorizations;
 import org.springframework.security.oauth2.server.authorization.TokenType;
 import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeAuthenticationToken;
+import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationGrantAuthenticationToken;
 import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
 import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
 import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
@@ -110,7 +111,7 @@ public class JwtEncodingContextTests {
 		assertThat(context.getAuthorization()).isEqualTo(authorization);
 		assertThat(context.getTokenType()).isEqualTo(TokenType.ACCESS_TOKEN);
 		assertThat(context.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE);
-		assertThat(context.<Authentication>getAuthorizationGrant()).isEqualTo(authorizationGrant);
+		assertThat(context.<OAuth2AuthorizationGrantAuthenticationToken>getAuthorizationGrant()).isEqualTo(authorizationGrant);
 		assertThat(context.<String>get("custom-key-1")).isEqualTo("custom-value-1");
 		assertThat(context.<String>get("custom-key-2")).isEqualTo("custom-value-2");
 	}

+ 0 - 114
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverterTests.java

@@ -1,114 +0,0 @@
-/*
- * Copyright 2020 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.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.oauth2.server.authorization.web;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.core.convert.converter.Converter;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockServletContext;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.oauth2.core.AuthorizationGrantType;
-import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
-import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken;
-import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientCredentialsAuthenticationToken;
-import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
-import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
-
-import javax.servlet.http.HttpServletRequest;
-import java.util.Collections;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.when;
-
-/**
- * Tests for {@link DelegatingAuthorizationGrantAuthenticationConverter}.
- *
- * @author Alexey Nesterov
- */
-public class DelegatingAuthorizationGrantAuthenticationConverterTests {
-	private Converter<HttpServletRequest, Authentication> clientCredentialsAuthenticationConverter;
-	private DelegatingAuthorizationGrantAuthenticationConverter authenticationConverter;
-
-	@Before
-	public void setUp() {
-		this.clientCredentialsAuthenticationConverter = mock(Converter.class);
-		Map<AuthorizationGrantType, Converter<HttpServletRequest, Authentication>> converters =
-				Collections.singletonMap(AuthorizationGrantType.CLIENT_CREDENTIALS, this.clientCredentialsAuthenticationConverter);
-		this.authenticationConverter = new DelegatingAuthorizationGrantAuthenticationConverter(converters);
-	}
-
-	@Test
-	public void constructorWhenConvertersEmptyThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> new DelegatingAuthorizationGrantAuthenticationConverter(Collections.emptyMap()))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("converters cannot be empty");
-	}
-
-	@Test
-	public void convertWhenRequestNullThenThrowIllegalArgumentException() {
-		assertThatThrownBy(() -> this.authenticationConverter.convert(null))
-				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessage("request cannot be null");
-	}
-
-	@Test
-	public void convertWhenGrantTypeMissingThenNull() {
-		MockHttpServletRequest request = MockMvcRequestBuilders
-				.post(OAuth2TokenEndpointFilter.DEFAULT_TOKEN_ENDPOINT_URI)
-				.buildRequest(new MockServletContext());
-
-		Authentication authentication = this.authenticationConverter.convert(request);
-		assertThat(authentication).isNull();
-		verifyNoInteractions(this.clientCredentialsAuthenticationConverter);
-	}
-
-	@Test
-	public void convertWhenGrantTypeUnsupportedThenNull() {
-		MockHttpServletRequest request = MockMvcRequestBuilders
-				.post(OAuth2TokenEndpointFilter.DEFAULT_TOKEN_ENDPOINT_URI)
-				.param(OAuth2ParameterNames.GRANT_TYPE, "extension_grant_type")
-				.buildRequest(new MockServletContext());
-
-		Authentication authentication = this.authenticationConverter.convert(request);
-		assertThat(authentication).isNull();
-		verifyNoInteractions(this.clientCredentialsAuthenticationConverter);
-	}
-
-	@Test
-	public void convertWhenGrantTypeSupportedThenConverterCalled() {
-		OAuth2ClientCredentialsAuthenticationToken expectedAuthentication =
-				new OAuth2ClientCredentialsAuthenticationToken(
-						new OAuth2ClientAuthenticationToken(
-								TestRegisteredClients.registeredClient().build()));
-		when(this.clientCredentialsAuthenticationConverter.convert(any())).thenReturn(expectedAuthentication);
-
-		MockHttpServletRequest request = MockMvcRequestBuilders
-				.post(OAuth2TokenEndpointFilter.DEFAULT_TOKEN_ENDPOINT_URI)
-				.param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
-				.buildRequest(new MockServletContext());
-
-		Authentication authentication = this.authenticationConverter.convert(request);
-		assertThat(authentication).isEqualTo(expectedAuthentication);
-		verify(this.clientCredentialsAuthenticationConverter).convert(request);
-	}
-}