From 218d49b134645899c10758b864e352a780012436 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Fri, 5 Feb 2021 06:30:12 -0500 Subject: [PATCH] Introduce base Authentication for authorization grant Closes gh-216 --- ...2AuthorizationCodeAuthenticationToken.java | 52 ++------ ...AuthorizationGrantAuthenticationToken.java | 91 ++++++++++++++ ...2ClientCredentialsAuthenticationToken.java | 32 ++--- ...OAuth2RefreshTokenAuthenticationToken.java | 32 ++--- .../token/OAuth2TokenContext.java | 5 +- ...orizationGrantAuthenticationConverter.java | 70 ----------- .../web/OAuth2TokenEndpointFilter.java | 50 ++++---- ...zationCodeAuthenticationProviderTests.java | 8 +- ...orizationCodeAuthenticationTokenTests.java | 11 +- ...redentialsAuthenticationProviderTests.java | 4 +- ...ntCredentialsAuthenticationTokenTests.java | 12 +- ...freshTokenAuthenticationProviderTests.java | 4 +- ...2RefreshTokenAuthenticationTokenTests.java | 11 +- .../token/JwtEncodingContextTests.java | 3 +- ...tionGrantAuthenticationConverterTests.java | 114 ------------------ 15 files changed, 179 insertions(+), 320 deletions(-) create mode 100644 oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationGrantAuthenticationToken.java delete mode 100644 oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverter.java delete mode 100644 oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverterTests.java diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationToken.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationToken.java index 08f4fb1..6f38750 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationToken.java +++ b/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 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.util.Assert; - -import java.util.Collections; import java.util.Map; +import org.springframework.lang.Nullable; +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 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 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 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 getAdditionalParameters() { - return this.additionalParameters; - } } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationGrantAuthenticationToken.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationGrantAuthenticationToken.java new file mode 100644 index 0000000..9ba7758 --- /dev/null +++ b/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 Section 1.3 Authorization Grant + */ +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 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 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 getAdditionalParameters() { + return this.additionalParameters; + } +} diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationToken.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationToken.java index 7b27ea2..27d9091 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationToken.java +++ b/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 scopes; /** @@ -54,23 +50,11 @@ public class OAuth2ClientCredentialsAuthenticationToken extends AbstractAuthenti * @param scopes the requested scope(s) */ public OAuth2ClientCredentialsAuthenticationToken(Authentication clientPrincipal, Set 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). * diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationToken.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationToken.java index 15c86df..9e20426 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationToken.java +++ b/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 scopes; /** @@ -57,25 +53,13 @@ public class OAuth2RefreshTokenAuthenticationToken extends AbstractAuthenticatio */ public OAuth2RefreshTokenAuthenticationToken(String refreshToken, Authentication clientPrincipal, Set 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. * diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2TokenContext.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2TokenContext.java index c57448d..29177ee 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2TokenContext.java +++ b/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 getAuthorizationGrant() { + default 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); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverter.java deleted file mode 100644 index bdf5d6e..0000000 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverter.java +++ /dev/null @@ -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 { - private final Map> converters; - - /** - * Constructs a {@code DelegatingAuthorizationGrantAuthenticationConverter} using the provided parameters. - * - * @param converters a {@code Map} of {@link Converter}(s) - */ - public DelegatingAuthorizationGrantAuthenticationConverter( - Map> 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 converter = - this.converters.get(new AuthorizationGrantType(grantType)); - if (converter == null) { - return null; - } - - return converter.convert(request); - } -} diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilter.java index d45abdd..6766a03 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilter.java +++ b/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 authorizationGrantAuthenticationConverter; + private final AuthenticationConverter authorizationGrantAuthenticationConverter; private final HttpMessageConverter accessTokenHttpResponseConverter = new OAuth2AccessTokenResponseHttpMessageConverter(); private final HttpMessageConverter 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> 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 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 { + 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 { + 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 { + private static class ClientCredentialsAuthenticationConverter implements AuthenticationConverter { @Override public Authentication convert(HttpServletRequest request) { diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java index e781610..fa7bc4d 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java +++ b/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.getAuthorizationGrant()).isEqualTo(authentication); + assertThat(jwtEncodingContext.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.getAuthorizationGrant()).isEqualTo(authentication); + assertThat(accessTokenContext.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.getAuthorizationGrant()).isEqualTo(authentication); + assertThat(idTokenContext.getAuthorizationGrant()).isEqualTo(authentication); assertThat(idTokenContext.getHeaders()).isNotNull(); assertThat(idTokenContext.getClaims()).isNotNull(); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationTokenTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationTokenTests.java index 9e7aff2..392ee3b 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationTokenTests.java +++ b/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); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProviderTests.java index 69a2133..7ab8f01 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProviderTests.java +++ b/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.getAuthorizationGrant()).isEqualTo(authentication); + assertThat(jwtEncodingContext.getAuthorizationGrant()).isEqualTo(authentication); assertThat(jwtEncodingContext.getHeaders()).isNotNull(); assertThat(jwtEncodingContext.getClaims()).isNotNull(); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationTokenTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationTokenTests.java index 1df80ea..73c6151 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationTokenTests.java +++ b/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); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProviderTests.java index bb8e017..c4981a4 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProviderTests.java +++ b/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.getAuthorizationGrant()).isEqualTo(authentication); + assertThat(jwtEncodingContext.getAuthorizationGrant()).isEqualTo(authentication); assertThat(jwtEncodingContext.getHeaders()).isNotNull(); assertThat(jwtEncodingContext.getClaims()).isNotNull(); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationTokenTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationTokenTests.java index 2dafaf9..ef9603b 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationTokenTests.java +++ b/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 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(); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/token/JwtEncodingContextTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/token/JwtEncodingContextTests.java index 88f4ea7..eff6f53 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/token/JwtEncodingContextTests.java +++ b/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.getAuthorizationGrant()).isEqualTo(authorizationGrant); + assertThat(context.getAuthorizationGrant()).isEqualTo(authorizationGrant); assertThat(context.get("custom-key-1")).isEqualTo("custom-value-1"); assertThat(context.get("custom-key-2")).isEqualTo("custom-value-2"); } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverterTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverterTests.java deleted file mode 100644 index dd47ad5..0000000 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/DelegatingAuthorizationGrantAuthenticationConverterTests.java +++ /dev/null @@ -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 clientCredentialsAuthenticationConverter; - private DelegatingAuthorizationGrantAuthenticationConverter authenticationConverter; - - @Before - public void setUp() { - this.clientCredentialsAuthenticationConverter = mock(Converter.class); - Map> 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); - } -}