diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/AbstractOAuth2AuthorizationServerMetadata.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/AbstractOAuth2AuthorizationServerMetadata.java index 08916869..a1bd0072 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/AbstractOAuth2AuthorizationServerMetadata.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/AbstractOAuth2AuthorizationServerMetadata.java @@ -38,10 +38,16 @@ import org.springframework.util.Assert; * @author Joe Grandja * @see OAuth2AuthorizationServerMetadataClaimAccessor * @since 0.1.1 - * @see 3.2. Authorization Server Metadata Response - * @see 4.2. OpenID Provider Configuration Response - * @see 4. Device Authorization Grant Metadata - * @see 3.3 Mutual-TLS Client Certificate-Bound Access Tokens Metadata + * @see 3.2. + * Authorization Server Metadata Response + * @see 4.2. + * OpenID Provider Configuration Response + * @see 4. + * Device Authorization Grant Metadata + * @see 3.3 Mutual-TLS Client + * Certificate-Bound Access Tokens Metadata */ public abstract class AbstractOAuth2AuthorizationServerMetadata implements OAuth2AuthorizationServerMetadataClaimAccessor, Serializable { @@ -358,14 +364,16 @@ public abstract class AbstractOAuth2AuthorizationServerMetadata } /** - * Use this {@code tls_client_certificate_bound_access_tokens} in the resulting {@link AbstractOAuth2AuthorizationServerMetadata}, OPTIONAL. - * - * @param tlsClientCertificateBoundAccessTokens {@code true} to indicate support for mutual-TLS client certificate-bound access tokens + * Use this {@code tls_client_certificate_bound_access_tokens} in the resulting + * {@link AbstractOAuth2AuthorizationServerMetadata}, OPTIONAL. + * @param tlsClientCertificateBoundAccessTokens {@code true} to indicate support + * for mutual-TLS client certificate-bound access tokens * @return the {@link AbstractBuilder} for further configuration * @since 1.3 */ public B tlsClientCertificateBoundAccessTokens(boolean tlsClientCertificateBoundAccessTokens) { - return claim(OAuth2AuthorizationServerMetadataClaimNames.TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKENS, tlsClientCertificateBoundAccessTokens); + return claim(OAuth2AuthorizationServerMetadataClaimNames.TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKENS, + tlsClientCertificateBoundAccessTokens); } /** diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimAccessor.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimAccessor.java index 6aab94ab..54c6057c 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimAccessor.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimAccessor.java @@ -30,10 +30,16 @@ import org.springframework.security.oauth2.core.ClaimAccessor; * @since 0.1.1 * @see ClaimAccessor * @see OAuth2AuthorizationServerMetadataClaimNames - * @see 2. Authorization Server Metadata - * @see 3. OpenID Provider Metadata - * @see 4. Device Authorization Grant Metadata - * @see 3.3 Mutual-TLS Client Certificate-Bound Access Tokens Metadata + * @see 2. + * Authorization Server Metadata + * @see 3. OpenID + * Provider Metadata + * @see 4. + * Device Authorization Grant Metadata + * @see 3.3 Mutual-TLS Client + * Certificate-Bound Access Tokens Metadata */ public interface OAuth2AuthorizationServerMetadataClaimAccessor extends ClaimAccessor { @@ -176,13 +182,15 @@ public interface OAuth2AuthorizationServerMetadataClaimAccessor extends ClaimAcc } /** - * Returns {@code true} to indicate support for mutual-TLS client certificate-bound access tokens {@code (tls_client_certificate_bound_access_tokens)}. - * - * @return {@code true} to indicate support for mutual-TLS client certificate-bound access tokens, {@code false} otherwise + * Returns {@code true} to indicate support for mutual-TLS client certificate-bound + * access tokens {@code (tls_client_certificate_bound_access_tokens)}. + * @return {@code true} to indicate support for mutual-TLS client certificate-bound + * access tokens, {@code false} otherwise * @since 1.3 */ default boolean isTlsClientCertificateBoundAccessTokens() { - return Boolean.TRUE.equals(getClaimAsBoolean(OAuth2AuthorizationServerMetadataClaimNames.TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKENS)); + return Boolean.TRUE.equals(getClaimAsBoolean( + OAuth2AuthorizationServerMetadataClaimNames.TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKENS)); } } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimNames.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimNames.java index ed47799a..0a410bf3 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimNames.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimNames.java @@ -22,10 +22,16 @@ package org.springframework.security.oauth2.server.authorization; * @author Daniel Garnier-Moiroux * @author Joe Grandja * @since 0.1.1 - * @see 2. Authorization Server Metadata - * @see 3. OpenID Provider Metadata - * @see 4. Device Authorization Grant Metadata - * @see 3.3 Mutual-TLS Client Certificate-Bound Access Tokens Metadata + * @see 2. + * Authorization Server Metadata + * @see 3. OpenID + * Provider Metadata + * @see 4. + * Device Authorization Grant Metadata + * @see 3.3 Mutual-TLS Client + * Certificate-Bound Access Tokens Metadata */ public class OAuth2AuthorizationServerMetadataClaimNames { @@ -118,7 +124,8 @@ public class OAuth2AuthorizationServerMetadataClaimNames { public static final String CODE_CHALLENGE_METHODS_SUPPORTED = "code_challenge_methods_supported"; /** - * {@code tls_client_certificate_bound_access_tokens} - {@code true} to indicate support for mutual-TLS client certificate-bound access tokens + * {@code tls_client_certificate_bound_access_tokens} - {@code true} to indicate + * support for mutual-TLS client certificate-bound access tokens * @since 1.3 */ public static final String TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKENS = "tls_client_certificate_bound_access_tokens"; diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/aot/hint/OAuth2AuthorizationServerBeanRegistrationAotProcessor.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/aot/hint/OAuth2AuthorizationServerBeanRegistrationAotProcessor.java index 32758fd5..5118d64b 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/aot/hint/OAuth2AuthorizationServerBeanRegistrationAotProcessor.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/aot/hint/OAuth2AuthorizationServerBeanRegistrationAotProcessor.java @@ -150,14 +150,14 @@ class OAuth2AuthorizationServerBeanRegistrationAotProcessor implements BeanRegis loadClass("org.springframework.security.jackson2.UserMixin")); this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass("org.springframework.security.jackson2.SimpleGrantedAuthorityMixin")); - this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), - loadClass("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2ActorAuthenticationTokenMixin")); - this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), - loadClass("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationRequestMixin")); - this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), - loadClass("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2CompositeAuthenticationTokenMixin")); - this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), - loadClass("org.springframework.security.oauth2.server.authorization.jackson2.OAuth2TokenFormatMixin")); + this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass( + "org.springframework.security.oauth2.server.authorization.jackson2.OAuth2ActorAuthenticationTokenMixin")); + this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass( + "org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationRequestMixin")); + this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass( + "org.springframework.security.oauth2.server.authorization.jackson2.OAuth2CompositeAuthenticationTokenMixin")); + this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass( + "org.springframework.security.oauth2.server.authorization.jackson2.OAuth2TokenFormatMixin")); // Check if Spring Security OAuth2 Client is on classpath if (ClassUtils.isPresent("org.springframework.security.oauth2.client.registration.ClientRegistration", diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AccessTokenAuthenticationContext.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AccessTokenAuthenticationContext.java index a9fc77ad..4f18a92f 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AccessTokenAuthenticationContext.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AccessTokenAuthenticationContext.java @@ -26,8 +26,9 @@ import org.springframework.security.oauth2.server.authorization.web.authenticati import org.springframework.util.Assert; /** - * An {@link OAuth2AuthenticationContext} that holds an {@link OAuth2AccessTokenAuthenticationToken} and additional information - * and is used when customizing the {@link OAuth2AccessTokenResponse}. + * An {@link OAuth2AuthenticationContext} that holds an + * {@link OAuth2AccessTokenAuthenticationToken} and additional information and is used + * when customizing the {@link OAuth2AccessTokenResponse}. * * @author Dmitriy Dubson * @since 1.3 @@ -37,6 +38,7 @@ import org.springframework.util.Assert; * @see OAuth2AccessTokenResponseAuthenticationSuccessHandler#setAccessTokenResponseCustomizer(Consumer) */ public final class OAuth2AccessTokenAuthenticationContext implements OAuth2AuthenticationContext { + private final Map context; private OAuth2AccessTokenAuthenticationContext(Map context) { @@ -57,8 +59,8 @@ public final class OAuth2AccessTokenAuthenticationContext implements OAuth2Authe } /** - * Returns the {@link OAuth2AccessTokenResponse.Builder access token response builder}. - * + * Returns the {@link OAuth2AccessTokenResponse.Builder access token response + * builder}. * @return the {@link OAuth2AccessTokenResponse.Builder} */ public OAuth2AccessTokenResponse.Builder getAccessTokenResponse() { @@ -66,8 +68,8 @@ public final class OAuth2AccessTokenAuthenticationContext implements OAuth2Authe } /** - * Constructs a new {@link Builder} with the provided {@link OAuth2AccessTokenAuthenticationToken}. - * + * Constructs a new {@link Builder} with the provided + * {@link OAuth2AccessTokenAuthenticationToken}. * @param authentication the {@link OAuth2AccessTokenAuthenticationToken} * @return the {@link Builder} */ @@ -85,8 +87,8 @@ public final class OAuth2AccessTokenAuthenticationContext implements OAuth2Authe } /** - * Sets the {@link OAuth2AccessTokenResponse.Builder access token response builder}. - * + * Sets the {@link OAuth2AccessTokenResponse.Builder access token response + * builder}. * @param accessTokenResponse the {@link OAuth2AccessTokenResponse.Builder} * @return the {@link Builder} for further configuration */ @@ -96,7 +98,6 @@ public final class OAuth2AccessTokenAuthenticationContext implements OAuth2Authe /** * Builds a new {@link OAuth2AccessTokenAuthenticationContext}. - * * @return the {@link OAuth2AccessTokenAuthenticationContext} */ public OAuth2AccessTokenAuthenticationContext build() { diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthenticationProviderUtils.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthenticationProviderUtils.java index 287856d3..f5b7be35 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthenticationProviderUtils.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthenticationProviderUtils.java @@ -81,11 +81,11 @@ final class OAuth2AuthenticationProviderUtils { static OAuth2AccessToken accessToken(OAuth2Authorization.Builder builder, T token, OAuth2TokenContext accessTokenContext) { - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - token.getTokenValue(), token.getIssuedAt(), token.getExpiresAt(), - accessTokenContext.getAuthorizedScopes()); - OAuth2TokenFormat accessTokenFormat = accessTokenContext.getRegisteredClient().getTokenSettings() - .getAccessTokenFormat(); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, token.getTokenValue(), + token.getIssuedAt(), token.getExpiresAt(), accessTokenContext.getAuthorizedScopes()); + OAuth2TokenFormat accessTokenFormat = accessTokenContext.getRegisteredClient() + .getTokenSettings() + .getAccessTokenFormat(); builder.token(accessToken, (metadata) -> { if (token instanceof ClaimAccessor claimAccessor) { metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, claimAccessor.getClaims()); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java index fbb3018c..519f23d9 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java @@ -157,11 +157,12 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } - if (StringUtils.hasText(authorizationRequest.getRedirectUri()) && - !authorizationRequest.getRedirectUri().equals(authorizationCodeAuthentication.getRedirectUri())) { + if (StringUtils.hasText(authorizationRequest.getRedirectUri()) + && !authorizationRequest.getRedirectUri().equals(authorizationCodeAuthentication.getRedirectUri())) { if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.format("Invalid request: redirect_uri does not match" + - " for registered client '%s'", registeredClient.getId())); + this.logger.debug(LogMessage.format( + "Invalid request: redirect_uri does not match" + " for registered client '%s'", + registeredClient.getId())); } throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationContext.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationContext.java index 285a11f0..35ea4f9b 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationContext.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationContext.java @@ -28,8 +28,10 @@ import org.springframework.security.oauth2.server.authorization.client.Registere import org.springframework.util.Assert; /** - * An {@link OAuth2AuthenticationContext} that holds an {@link OAuth2AuthorizationCodeRequestAuthenticationToken} and additional information - * and is used when validating the OAuth 2.0 Authorization Request parameters, as well as, determining if authorization consent is required. + * An {@link OAuth2AuthenticationContext} that holds an + * {@link OAuth2AuthorizationCodeRequestAuthenticationToken} and additional information + * and is used when validating the OAuth 2.0 Authorization Request parameters, as well as, + * determining if authorization consent is required. * * @author Joe Grandja * @since 0.4.0 @@ -69,7 +71,6 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationContext implement /** * Returns the {@link OAuth2AuthorizationRequest authorization request}. - * * @return the {@link OAuth2AuthorizationRequest} * @since 1.3 */ @@ -80,7 +81,6 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationContext implement /** * Returns the {@link OAuth2AuthorizationConsent authorization consent}. - * * @return the {@link OAuth2AuthorizationConsent} * @since 1.3 */ @@ -89,10 +89,9 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationContext implement return get(OAuth2AuthorizationConsent.class); } - /** - * Constructs a new {@link Builder} with the provided {@link OAuth2AuthorizationCodeRequestAuthenticationToken}. - * + * Constructs a new {@link Builder} with the provided + * {@link OAuth2AuthorizationCodeRequestAuthenticationToken}. * @param authentication the {@link OAuth2AuthorizationCodeRequestAuthenticationToken} * @return the {@link Builder} */ @@ -121,7 +120,6 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationContext implement /** * Sets the {@link OAuth2AuthorizationRequest authorization request}. - * * @param authorizationRequest the {@link OAuth2AuthorizationRequest} * @return the {@link Builder} for further configuration * @since 1.3 @@ -132,7 +130,6 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationContext implement /** * Sets the {@link OAuth2AuthorizationConsent authorization consent}. - * * @param authorizationConsent the {@link OAuth2AuthorizationConsent} * @return the {@link Builder} for further configuration * @since 1.3 diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java index 81e5e691..f6bc97e2 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProvider.java @@ -90,10 +90,9 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen private OAuth2TokenGenerator authorizationCodeGenerator = new OAuth2AuthorizationCodeGenerator(); - private Consumer authenticationValidator = - new OAuth2AuthorizationCodeRequestAuthenticationValidator(); - private Predicate authorizationConsentRequired = - OAuth2AuthorizationCodeRequestAuthenticationProvider::isAuthorizationConsentRequired; + private Consumer authenticationValidator = new OAuth2AuthorizationCodeRequestAuthenticationValidator(); + + private Predicate authorizationConsentRequired = OAuth2AuthorizationCodeRequestAuthenticationProvider::isAuthorizationConsentRequired; /** * Constructs an {@code OAuth2AuthorizationCodeRequestAuthenticationProvider} using @@ -128,15 +127,16 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen this.logger.trace("Retrieved registered client"); } - OAuth2AuthorizationCodeRequestAuthenticationContext.Builder authenticationContextBuilder = - OAuth2AuthorizationCodeRequestAuthenticationContext.with(authorizationCodeRequestAuthentication) - .registeredClient(registeredClient); + OAuth2AuthorizationCodeRequestAuthenticationContext.Builder authenticationContextBuilder = OAuth2AuthorizationCodeRequestAuthenticationContext + .with(authorizationCodeRequestAuthentication) + .registeredClient(registeredClient); this.authenticationValidator.accept(authenticationContextBuilder.build()); if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.AUTHORIZATION_CODE)) { if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.format("Invalid request: requested grant_type is not allowed" + - " for registered client '%s'", registeredClient.getId())); + this.logger.debug(LogMessage.format( + "Invalid request: requested grant_type is not allowed" + " for registered client '%s'", + registeredClient.getId())); } throwError(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT, OAuth2ParameterNames.CLIENT_ID, authorizationCodeRequestAuthentication, registeredClient); @@ -176,17 +176,17 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen } OAuth2AuthorizationRequest authorizationRequest = OAuth2AuthorizationRequest.authorizationCode() - .authorizationUri(authorizationCodeRequestAuthentication.getAuthorizationUri()) - .clientId(registeredClient.getClientId()) - .redirectUri(authorizationCodeRequestAuthentication.getRedirectUri()) - .scopes(authorizationCodeRequestAuthentication.getScopes()) - .state(authorizationCodeRequestAuthentication.getState()) - .additionalParameters(authorizationCodeRequestAuthentication.getAdditionalParameters()) - .build(); + .authorizationUri(authorizationCodeRequestAuthentication.getAuthorizationUri()) + .clientId(registeredClient.getClientId()) + .redirectUri(authorizationCodeRequestAuthentication.getRedirectUri()) + .scopes(authorizationCodeRequestAuthentication.getScopes()) + .state(authorizationCodeRequestAuthentication.getState()) + .additionalParameters(authorizationCodeRequestAuthentication.getAdditionalParameters()) + .build(); authenticationContextBuilder.authorizationRequest(authorizationRequest); - OAuth2AuthorizationConsent currentAuthorizationConsent = this.authorizationConsentService.findById( - registeredClient.getId(), principal.getName()); + OAuth2AuthorizationConsent currentAuthorizationConsent = this.authorizationConsentService + .findById(registeredClient.getId(), principal.getName()); if (currentAuthorizationConsent != null) { authenticationContextBuilder.authorizationConsent(currentAuthorizationConsent); } @@ -295,42 +295,48 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen * Sets the {@code Predicate} used to determine if authorization consent is required. * *

- * The {@link OAuth2AuthorizationCodeRequestAuthenticationContext} gives the predicate access to the {@link OAuth2AuthorizationCodeRequestAuthenticationToken}, - * as well as, the following context attributes: + * The {@link OAuth2AuthorizationCodeRequestAuthenticationContext} gives the predicate + * access to the {@link OAuth2AuthorizationCodeRequestAuthenticationToken}, as well + * as, the following context attributes: *

    *
  • The {@link RegisteredClient} associated with the authorization request.
  • - *
  • The {@link OAuth2AuthorizationRequest} containing the authorization request parameters.
  • - *
  • The {@link OAuth2AuthorizationConsent} previously granted to the {@link RegisteredClient}, or {@code null} if not available.
  • + *
  • The {@link OAuth2AuthorizationRequest} containing the authorization request + * parameters.
  • + *
  • The {@link OAuth2AuthorizationConsent} previously granted to the + * {@link RegisteredClient}, or {@code null} if not available.
  • *
- * - * @param authorizationConsentRequired the {@code Predicate} used to determine if authorization consent is required + * @param authorizationConsentRequired the {@code Predicate} used to determine if + * authorization consent is required * @since 1.3 */ - public void setAuthorizationConsentRequired(Predicate authorizationConsentRequired) { + public void setAuthorizationConsentRequired( + Predicate authorizationConsentRequired) { Assert.notNull(authorizationConsentRequired, "authorizationConsentRequired cannot be null"); this.authorizationConsentRequired = authorizationConsentRequired; } - private static boolean isAuthorizationConsentRequired(OAuth2AuthorizationCodeRequestAuthenticationContext authenticationContext) { + private static boolean isAuthorizationConsentRequired( + OAuth2AuthorizationCodeRequestAuthenticationContext authenticationContext) { if (!authenticationContext.getRegisteredClient().getClientSettings().isRequireAuthorizationConsent()) { return false; } // 'openid' scope does not require consent - if (authenticationContext.getAuthorizationRequest().getScopes().contains(OidcScopes.OPENID) && - authenticationContext.getAuthorizationRequest().getScopes().size() == 1) { + if (authenticationContext.getAuthorizationRequest().getScopes().contains(OidcScopes.OPENID) + && authenticationContext.getAuthorizationRequest().getScopes().size() == 1) { return false; } - if (authenticationContext.getAuthorizationConsent() != null && - authenticationContext.getAuthorizationConsent().getScopes().containsAll(authenticationContext.getAuthorizationRequest().getScopes())) { + if (authenticationContext.getAuthorizationConsent() != null && authenticationContext.getAuthorizationConsent() + .getScopes() + .containsAll(authenticationContext.getAuthorizationRequest().getScopes())) { return false; } return true; } - private static OAuth2Authorization.Builder authorizationBuilder(RegisteredClient registeredClient, Authentication principal, - OAuth2AuthorizationRequest authorizationRequest) { + private static OAuth2Authorization.Builder authorizationBuilder(RegisteredClient registeredClient, + Authentication principal, OAuth2AuthorizationRequest authorizationRequest) { return OAuth2Authorization.withRegisteredClient(registeredClient) .principalName(principal.getName()) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientAuthenticationContext.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientAuthenticationContext.java index 93201f58..936759b8 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientAuthenticationContext.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientAuthenticationContext.java @@ -25,8 +25,9 @@ import org.springframework.security.oauth2.server.authorization.client.Registere import org.springframework.util.Assert; /** - * An {@link OAuth2AuthenticationContext} that holds an {@link OAuth2ClientAuthenticationToken} and additional information - * and is used when validating an OAuth 2.0 Client Authentication. + * An {@link OAuth2AuthenticationContext} that holds an + * {@link OAuth2ClientAuthenticationToken} and additional information and is used when + * validating an OAuth 2.0 Client Authentication. * * @author Joe Grandja * @since 1.3 @@ -35,6 +36,7 @@ import org.springframework.util.Assert; * @see X509ClientCertificateAuthenticationProvider#setCertificateVerifier(Consumer) */ public final class OAuth2ClientAuthenticationContext implements OAuth2AuthenticationContext { + private final Map context; private OAuth2ClientAuthenticationContext(Map context) { @@ -56,7 +58,6 @@ public final class OAuth2ClientAuthenticationContext implements OAuth2Authentica /** * Returns the {@link RegisteredClient registered client}. - * * @return the {@link RegisteredClient} */ public RegisteredClient getRegisteredClient() { @@ -64,8 +65,8 @@ public final class OAuth2ClientAuthenticationContext implements OAuth2Authentica } /** - * Constructs a new {@link Builder} with the provided {@link OAuth2ClientAuthenticationToken}. - * + * Constructs a new {@link Builder} with the provided + * {@link OAuth2ClientAuthenticationToken}. * @param authentication the {@link OAuth2ClientAuthenticationToken} * @return the {@link Builder} */ @@ -84,7 +85,6 @@ public final class OAuth2ClientAuthenticationContext implements OAuth2Authentica /** * Sets the {@link RegisteredClient registered client}. - * * @param registeredClient the {@link RegisteredClient} * @return the {@link Builder} for further configuration */ @@ -94,7 +94,6 @@ public final class OAuth2ClientAuthenticationContext implements OAuth2Authentica /** * Builds a new {@link OAuth2ClientAuthenticationContext}. - * * @return the {@link OAuth2ClientAuthenticationContext} */ public OAuth2ClientAuthenticationContext build() { diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationContext.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationContext.java index f95e347a..07448434 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationContext.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationContext.java @@ -25,8 +25,9 @@ import org.springframework.security.oauth2.server.authorization.client.Registere import org.springframework.util.Assert; /** - * An {@link OAuth2AuthenticationContext} that holds an {@link OAuth2ClientCredentialsAuthenticationToken} and additional information - * and is used when validating the OAuth 2.0 Client Credentials Grant Request. + * An {@link OAuth2AuthenticationContext} that holds an + * {@link OAuth2ClientCredentialsAuthenticationToken} and additional information and is + * used when validating the OAuth 2.0 Client Credentials Grant Request. * * @author Adam Pilling * @since 1.3 @@ -35,6 +36,7 @@ import org.springframework.util.Assert; * @see OAuth2ClientCredentialsAuthenticationProvider#setAuthenticationValidator(Consumer) */ public final class OAuth2ClientCredentialsAuthenticationContext implements OAuth2AuthenticationContext { + private final Map context; private OAuth2ClientCredentialsAuthenticationContext(Map context) { @@ -56,7 +58,6 @@ public final class OAuth2ClientCredentialsAuthenticationContext implements OAuth /** * Returns the {@link RegisteredClient registered client}. - * * @return the {@link RegisteredClient} */ public RegisteredClient getRegisteredClient() { @@ -64,8 +65,8 @@ public final class OAuth2ClientCredentialsAuthenticationContext implements OAuth } /** - * Constructs a new {@link Builder} with the provided {@link OAuth2ClientCredentialsAuthenticationToken}. - * + * Constructs a new {@link Builder} with the provided + * {@link OAuth2ClientCredentialsAuthenticationToken}. * @param authentication the {@link OAuth2ClientCredentialsAuthenticationToken} * @return the {@link Builder} */ @@ -84,7 +85,6 @@ public final class OAuth2ClientCredentialsAuthenticationContext implements OAuth /** * Sets the {@link RegisteredClient registered client}. - * * @param registeredClient the {@link RegisteredClient} * @return the {@link Builder} for further configuration */ @@ -94,7 +94,6 @@ public final class OAuth2ClientCredentialsAuthenticationContext implements OAuth /** * Builds a new {@link OAuth2ClientCredentialsAuthenticationContext}. - * * @return the {@link OAuth2ClientCredentialsAuthenticationContext} */ public OAuth2ClientCredentialsAuthenticationContext build() { diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java index 8dab8d14..f0f4fa70 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java @@ -71,8 +71,8 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth private final OAuth2AuthorizationService authorizationService; private final OAuth2TokenGenerator tokenGenerator; - private Consumer authenticationValidator = - new OAuth2ClientCredentialsAuthenticationValidator(); + + private Consumer authenticationValidator = new OAuth2ClientCredentialsAuthenticationValidator(); /** * Constructs an {@code OAuth2ClientCredentialsAuthenticationProvider} using the @@ -103,16 +103,17 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.CLIENT_CREDENTIALS)) { if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.format("Invalid request: requested grant_type is not allowed" + - " for registered client '%s'", registeredClient.getId())); + this.logger.debug(LogMessage.format( + "Invalid request: requested grant_type is not allowed" + " for registered client '%s'", + registeredClient.getId())); } throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT); } - OAuth2ClientCredentialsAuthenticationContext authenticationContext = - OAuth2ClientCredentialsAuthenticationContext.with(clientCredentialsAuthentication) - .registeredClient(registeredClient) - .build(); + OAuth2ClientCredentialsAuthenticationContext authenticationContext = OAuth2ClientCredentialsAuthenticationContext + .with(clientCredentialsAuthentication) + .registeredClient(registeredClient) + .build(); this.authenticationValidator.accept(authenticationContext); Set authorizedScopes = new LinkedHashSet<>(clientCredentialsAuthentication.getScopes()); @@ -173,18 +174,22 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth } /** - * Sets the {@code Consumer} providing access to the {@link OAuth2ClientCredentialsAuthenticationContext} - * and is responsible for validating specific OAuth 2.0 Client Credentials Grant Request parameters - * associated in the {@link OAuth2ClientCredentialsAuthenticationToken}. - * The default authentication validator is {@link OAuth2ClientCredentialsAuthenticationValidator}. + * Sets the {@code Consumer} providing access to the + * {@link OAuth2ClientCredentialsAuthenticationContext} and is responsible for + * validating specific OAuth 2.0 Client Credentials Grant Request parameters + * associated in the {@link OAuth2ClientCredentialsAuthenticationToken}. The default + * authentication validator is {@link OAuth2ClientCredentialsAuthenticationValidator}. * *

- * NOTE: The authentication validator MUST throw {@link OAuth2AuthenticationException} if validation fails. - * - * @param authenticationValidator the {@code Consumer} providing access to the {@link OAuth2ClientCredentialsAuthenticationContext} and is responsible for validating specific OAuth 2.0 Client Credentials Grant Request parameters + * NOTE: The authentication validator MUST throw + * {@link OAuth2AuthenticationException} if validation fails. + * @param authenticationValidator the {@code Consumer} providing access to the + * {@link OAuth2ClientCredentialsAuthenticationContext} and is responsible for + * validating specific OAuth 2.0 Client Credentials Grant Request parameters * @since 1.3 */ - public void setAuthenticationValidator(Consumer authenticationValidator) { + public void setAuthenticationValidator( + Consumer authenticationValidator) { Assert.notNull(authenticationValidator, "authenticationValidator cannot be null"); this.authenticationValidator = authenticationValidator; } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationValidator.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationValidator.java index 31146ba7..7c721dcd 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationValidator.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationValidator.java @@ -27,14 +27,17 @@ import org.springframework.security.oauth2.core.OAuth2ErrorCodes; import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; /** - * A {@code Consumer} providing access to the {@link OAuth2ClientCredentialsAuthenticationContext} - * containing an {@link OAuth2ClientCredentialsAuthenticationToken} - * and is the default {@link OAuth2ClientCredentialsAuthenticationProvider#setAuthenticationValidator(Consumer) authentication validator} - * used for validating specific OAuth 2.0 Client Credentials Grant Request parameters. + * A {@code Consumer} providing access to the + * {@link OAuth2ClientCredentialsAuthenticationContext} containing an + * {@link OAuth2ClientCredentialsAuthenticationToken} and is the default + * {@link OAuth2ClientCredentialsAuthenticationProvider#setAuthenticationValidator(Consumer) + * authentication validator} used for validating specific OAuth 2.0 Client Credentials + * Grant Request parameters. * *

- * The default implementation validates {@link OAuth2ClientCredentialsAuthenticationToken#getScopes()}. - * If validation fails, an {@link OAuth2AuthenticationException} is thrown. + * The default implementation validates + * {@link OAuth2ClientCredentialsAuthenticationToken#getScopes()}. If validation fails, an + * {@link OAuth2AuthenticationException} is thrown. * * @author Adam Pilling * @since 1.3 @@ -42,14 +45,16 @@ import org.springframework.security.oauth2.server.authorization.client.Registere * @see OAuth2ClientCredentialsAuthenticationToken * @see OAuth2ClientCredentialsAuthenticationProvider#setAuthenticationValidator(Consumer) */ -public final class OAuth2ClientCredentialsAuthenticationValidator implements Consumer { +public final class OAuth2ClientCredentialsAuthenticationValidator + implements Consumer { + private static final Log LOGGER = LogFactory.getLog(OAuth2ClientCredentialsAuthenticationValidator.class); /** - * The default validator for {@link OAuth2ClientCredentialsAuthenticationToken#getScopes()}. + * The default validator for + * {@link OAuth2ClientCredentialsAuthenticationToken#getScopes()}. */ - public static final Consumer DEFAULT_SCOPE_VALIDATOR = - OAuth2ClientCredentialsAuthenticationValidator::validateScope; + public static final Consumer DEFAULT_SCOPE_VALIDATOR = OAuth2ClientCredentialsAuthenticationValidator::validateScope; private final Consumer authenticationValidator = DEFAULT_SCOPE_VALIDATOR; @@ -59,16 +64,17 @@ public final class OAuth2ClientCredentialsAuthenticationValidator implements Con } private static void validateScope(OAuth2ClientCredentialsAuthenticationContext authenticationContext) { - OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication = - authenticationContext.getAuthentication(); + OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication = authenticationContext + .getAuthentication(); RegisteredClient registeredClient = authenticationContext.getRegisteredClient(); Set requestedScopes = clientCredentialsAuthentication.getScopes(); Set allowedScopes = registeredClient.getScopes(); if (!requestedScopes.isEmpty() && !allowedScopes.containsAll(requestedScopes)) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(LogMessage.format("Invalid request: requested scope is not allowed" + - " for registered client '%s'", registeredClient.getId())); + LOGGER.debug(LogMessage.format( + "Invalid request: requested scope is not allowed" + " for registered client '%s'", + registeredClient.getId())); } throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_SCOPE); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceAuthorizationRequestAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceAuthorizationRequestAuthenticationProvider.java index 9fc29f09..0c4edaed 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceAuthorizationRequestAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceAuthorizationRequestAuthenticationProvider.java @@ -108,8 +108,9 @@ public final class OAuth2DeviceAuthorizationRequestAuthenticationProvider implem if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.DEVICE_CODE)) { if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.format("Invalid request: requested grant_type is not allowed" + - " for registered client '%s'", registeredClient.getId())); + this.logger.debug(LogMessage.format( + "Invalid request: requested grant_type is not allowed" + " for registered client '%s'", + registeredClient.getId())); } throwError(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT, OAuth2ParameterNames.CLIENT_ID); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java index 0fbdf8ab..6e079b10 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java @@ -127,8 +127,9 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.REFRESH_TOKEN)) { if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.format("Invalid request: requested grant_type is not allowed" + - " for registered client '%s'", registeredClient.getId())); + this.logger.debug(LogMessage.format( + "Invalid request: requested grant_type is not allowed" + " for registered client '%s'", + registeredClient.getId())); } throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT); } @@ -137,10 +138,12 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic if (!refreshToken.isActive()) { // As per https://tools.ietf.org/html/rfc6749#section-5.2 // invalid_grant: The provided authorization grant (e.g., authorization code, - // resource owner credentials) or refresh token is invalid, expired, revoked [...]. + // resource owner credentials) or refresh token is invalid, expired, revoked + // [...]. if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.format("Invalid request: refresh_token is not active" + - " for registered client '%s'", registeredClient.getId())); + this.logger.debug(LogMessage.format( + "Invalid request: refresh_token is not active" + " for registered client '%s'", + registeredClient.getId())); } throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeActor.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeActor.java index 3e868c6c..475b7620 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeActor.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeActor.java @@ -25,8 +25,9 @@ import org.springframework.security.oauth2.server.authorization.token.OAuth2Toke import org.springframework.util.Assert; /** - * A {@link ClaimAccessor} used for the OAuth 2.0 Token Exchange Grant to represent an actor in a - * {@link OAuth2TokenExchangeCompositeAuthenticationToken} (e.g. the "delegation" use case). + * A {@link ClaimAccessor} used for the OAuth 2.0 Token Exchange Grant to represent an + * actor in a {@link OAuth2TokenExchangeCompositeAuthenticationToken} (e.g. the + * "delegation" use case). * * @author Steve Riesenberg * @since 1.3 diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProvider.java index 59cbdf2a..1b0b09c8 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProvider.java @@ -55,7 +55,8 @@ import org.springframework.util.StringUtils; import static org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthenticationProviderUtils.getAuthenticatedClientElseThrowInvalidClient; /** - * An {@link AuthenticationProvider} implementation for the OAuth 2.0 Token Exchange Grant. + * An {@link AuthenticationProvider} implementation for the OAuth 2.0 Token Exchange + * Grant. * * @author Steve Riesenberg * @since 1.3 @@ -63,8 +64,10 @@ import static org.springframework.security.oauth2.server.authorization.authentic * @see OAuth2AccessTokenAuthenticationToken * @see OAuth2AuthorizationService * @see OAuth2TokenGenerator - * @see Section 1 Introduction - * @see Section 2.1 Request + * @see Section 1 Introduction + * @see Section 2.1 Request */ public final class OAuth2TokenExchangeAuthenticationProvider implements AuthenticationProvider { @@ -83,8 +86,8 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti private final OAuth2TokenGenerator tokenGenerator; /** - * Constructs an {@code OAuth2TokenExchangeAuthenticationProvider} using the provided parameters. - * + * Constructs an {@code OAuth2TokenExchangeAuthenticationProvider} using the provided + * parameters. * @param authorizationService the authorization service * @param tokenGenerator the token generator */ @@ -98,11 +101,10 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { - OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthentication = - (OAuth2TokenExchangeAuthenticationToken) authentication; + OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthentication = (OAuth2TokenExchangeAuthenticationToken) authentication; - OAuth2ClientAuthenticationToken clientPrincipal = - getAuthenticatedClientElseThrowInvalidClient(tokenExchangeAuthentication); + OAuth2ClientAuthenticationToken clientPrincipal = getAuthenticatedClientElseThrowInvalidClient( + tokenExchangeAuthentication); RegisteredClient registeredClient = clientPrincipal.getRegisteredClient(); if (this.logger.isTraceEnabled()) { @@ -113,13 +115,14 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT); } - if (JWT_TOKEN_TYPE_VALUE.equals(tokenExchangeAuthentication.getRequestedTokenType()) && - !OAuth2TokenFormat.SELF_CONTAINED.equals(registeredClient.getTokenSettings().getAccessTokenFormat())) { + if (JWT_TOKEN_TYPE_VALUE.equals(tokenExchangeAuthentication.getRequestedTokenType()) + && !OAuth2TokenFormat.SELF_CONTAINED + .equals(registeredClient.getTokenSettings().getAccessTokenFormat())) { throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST); } - OAuth2Authorization subjectAuthorization = this.authorizationService.findByToken( - tokenExchangeAuthentication.getSubjectToken(), OAuth2TokenType.ACCESS_TOKEN); + OAuth2Authorization subjectAuthorization = this.authorizationService + .findByToken(tokenExchangeAuthentication.getSubjectToken(), OAuth2TokenType.ACCESS_TOKEN); if (subjectAuthorization == null) { throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } @@ -128,12 +131,13 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti this.logger.trace("Retrieved authorization with subject token"); } - OAuth2Authorization.Token subjectToken = subjectAuthorization.getToken( - tokenExchangeAuthentication.getSubjectToken()); + OAuth2Authorization.Token subjectToken = subjectAuthorization + .getToken(tokenExchangeAuthentication.getSubjectToken()); if (!subjectToken.isActive()) { // As per https://tools.ietf.org/html/rfc6749#section-5.2 // invalid_grant: The provided authorization grant (e.g., authorization code, - // resource owner credentials) or refresh token is invalid, expired, revoked [...]. + // resource owner credentials) or refresh token is invalid, expired, revoked + // [...]. throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } @@ -152,16 +156,15 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti // The may_act claim makes a statement that one party is authorized to // become the actor and act on behalf of another party. Map authorizedActorClaims = null; - if (subjectToken.getClaims() != null && - subjectToken.getClaims().containsKey(MAY_ACT) && - subjectToken.getClaims().get(MAY_ACT) instanceof Map mayAct) { + if (subjectToken.getClaims() != null && subjectToken.getClaims().containsKey(MAY_ACT) + && subjectToken.getClaims().get(MAY_ACT) instanceof Map mayAct) { authorizedActorClaims = (Map) mayAct; } OAuth2Authorization actorAuthorization = null; if (StringUtils.hasText(tokenExchangeAuthentication.getActorToken())) { - actorAuthorization = this.authorizationService.findByToken( - tokenExchangeAuthentication.getActorToken(), OAuth2TokenType.ACCESS_TOKEN); + actorAuthorization = this.authorizationService.findByToken(tokenExchangeAuthentication.getActorToken(), + OAuth2TokenType.ACCESS_TOKEN); if (actorAuthorization == null) { throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } @@ -170,12 +173,14 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti this.logger.trace("Retrieved authorization with actor token"); } - OAuth2Authorization.Token actorToken = actorAuthorization.getToken( - tokenExchangeAuthentication.getActorToken()); + OAuth2Authorization.Token actorToken = actorAuthorization + .getToken(tokenExchangeAuthentication.getActorToken()); if (!actorToken.isActive()) { // As per https://tools.ietf.org/html/rfc6749#section-5.2 - // invalid_grant: The provided authorization grant (e.g., authorization code, - // resource owner credentials) or refresh token is invalid, expired, revoked [...]. + // invalid_grant: The provided authorization grant (e.g., authorization + // code, + // resource owner credentials) or refresh token is invalid, expired, + // revoked [...]. throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } @@ -187,14 +192,16 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti validateClaims(authorizedActorClaims, actorToken.getClaims(), OAuth2TokenClaimNames.ISS, OAuth2TokenClaimNames.SUB); } - } else if (authorizedActorClaims != null) { + } + else if (authorizedActorClaims != null) { throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } Set authorizedScopes = Collections.emptySet(); if (!CollectionUtils.isEmpty(tokenExchangeAuthentication.getScopes())) { authorizedScopes = validateRequestedScopes(registeredClient, tokenExchangeAuthentication.getScopes()); - } else if (!CollectionUtils.isEmpty(subjectAuthorization.getAuthorizedScopes())) { + } + else if (!CollectionUtils.isEmpty(subjectAuthorization.getAuthorizedScopes())) { authorizedScopes = validateRequestedScopes(registeredClient, subjectAuthorization.getAuthorizedScopes()); } @@ -248,21 +255,21 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti } Map additionalParameters = new HashMap<>(); - additionalParameters.put(OAuth2ParameterNames.ISSUED_TOKEN_TYPE, tokenExchangeAuthentication.getRequestedTokenType()); + additionalParameters.put(OAuth2ParameterNames.ISSUED_TOKEN_TYPE, + tokenExchangeAuthentication.getRequestedTokenType()); if (this.logger.isTraceEnabled()) { this.logger.trace("Authenticated token request"); } - return new OAuth2AccessTokenAuthenticationToken( - registeredClient, clientPrincipal, accessToken, null, additionalParameters); + return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken, null, + additionalParameters); } private static boolean isValidTokenType(String tokenType, OAuth2Authorization.Token token) { String tokenFormat = token.getMetadata(OAuth2TokenFormat.class.getName()); - return ACCESS_TOKEN_TYPE_VALUE.equals(tokenType) || - JWT_TOKEN_TYPE_VALUE.equals(tokenType) && - OAuth2TokenFormat.SELF_CONTAINED.getValue().equals(tokenFormat); + return ACCESS_TOKEN_TYPE_VALUE.equals(tokenType) || JWT_TOKEN_TYPE_VALUE.equals(tokenType) + && OAuth2TokenFormat.SELF_CONTAINED.getValue().equals(tokenFormat); } private static Set validateRequestedScopes(RegisteredClient registeredClient, Set requestedScopes) { @@ -275,7 +282,8 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti return new LinkedHashSet<>(requestedScopes); } - private static void validateClaims(Map expectedClaims, Map actualClaims, String... claimNames) { + private static void validateClaims(Map expectedClaims, Map actualClaims, + String... claimNames) { if (actualClaims == null) { throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT); } @@ -287,7 +295,8 @@ public final class OAuth2TokenExchangeAuthenticationProvider implements Authenti } } - private static Authentication getPrincipal(OAuth2Authorization subjectAuthorization, OAuth2Authorization actorAuthorization) { + private static Authentication getPrincipal(OAuth2Authorization subjectAuthorization, + OAuth2Authorization actorAuthorization) { Authentication subjectPrincipal = subjectAuthorization.getAttribute(Principal.class.getName()); if (actorAuthorization == null) { if (subjectPrincipal instanceof OAuth2TokenExchangeCompositeAuthenticationToken compositeAuthenticationToken) { diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationToken.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationToken.java index f1615777..944c4458 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationToken.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationToken.java @@ -53,8 +53,8 @@ public class OAuth2TokenExchangeAuthenticationToken extends OAuth2AuthorizationG private final Set scopes; /** - * Constructs an {@code OAuth2TokenExchangeAuthenticationToken} using the provided parameters. - * + * Constructs an {@code OAuth2TokenExchangeAuthenticationToken} using the provided + * parameters. * @param requestedTokenType the requested token type * @param subjectToken the subject token * @param subjectTokenType the subject token type @@ -79,17 +79,15 @@ public class OAuth2TokenExchangeAuthenticationToken extends OAuth2AuthorizationG this.subjectTokenType = subjectTokenType; this.actorToken = actorToken; this.actorTokenType = actorTokenType; - this.resources = Collections.unmodifiableSet( - resources != null ? new LinkedHashSet<>(resources) : Collections.emptySet()); - this.audiences = Collections.unmodifiableSet( - audiences != null ? new LinkedHashSet<>(audiences) : Collections.emptySet()); - this.scopes = Collections.unmodifiableSet( - scopes != null ? new HashSet<>(scopes) : Collections.emptySet()); + this.resources = Collections + .unmodifiableSet(resources != null ? new LinkedHashSet<>(resources) : Collections.emptySet()); + this.audiences = Collections + .unmodifiableSet(audiences != null ? new LinkedHashSet<>(audiences) : Collections.emptySet()); + this.scopes = Collections.unmodifiableSet(scopes != null ? new HashSet<>(scopes) : Collections.emptySet()); } /** * Returns the requested token type. - * * @return the requested token type */ public String getRequestedTokenType() { @@ -98,7 +96,6 @@ public class OAuth2TokenExchangeAuthenticationToken extends OAuth2AuthorizationG /** * Returns the subject token. - * * @return the subject token */ public String getSubjectToken() { @@ -107,7 +104,6 @@ public class OAuth2TokenExchangeAuthenticationToken extends OAuth2AuthorizationG /** * Returns the subject token type. - * * @return the subject token type */ public String getSubjectTokenType() { @@ -116,7 +112,6 @@ public class OAuth2TokenExchangeAuthenticationToken extends OAuth2AuthorizationG /** * Returns the actor token. - * * @return the actor token */ public String getActorToken() { @@ -125,7 +120,6 @@ public class OAuth2TokenExchangeAuthenticationToken extends OAuth2AuthorizationG /** * Returns the actor token type. - * * @return the actor token type */ public String getActorTokenType() { @@ -134,7 +128,6 @@ public class OAuth2TokenExchangeAuthenticationToken extends OAuth2AuthorizationG /** * Returns the requested resource URI(s). - * * @return the requested resource URI(s), or an empty {@code Set} if not available */ public Set getResources() { @@ -143,7 +136,6 @@ public class OAuth2TokenExchangeAuthenticationToken extends OAuth2AuthorizationG /** * Returns the requested audience value(s). - * * @return the requested audience value(s), or an empty {@code Set} if not available */ public Set getAudiences() { @@ -152,7 +144,6 @@ public class OAuth2TokenExchangeAuthenticationToken extends OAuth2AuthorizationG /** * Returns the requested scope(s). - * * @return the requested scope(s), or an empty {@code Set} if not available */ public Set getScopes() { diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeCompositeAuthenticationToken.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeCompositeAuthenticationToken.java index 458db85a..e9c20bd8 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeCompositeAuthenticationToken.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeCompositeAuthenticationToken.java @@ -26,8 +26,8 @@ import org.springframework.security.core.Authentication; import org.springframework.util.Assert; /** - * An {@link Authentication} implementation used for the OAuth 2.0 Token Exchange Grant - * to represent the principal in a composite token (e.g. the "delegation" use case). + * An {@link Authentication} implementation used for the OAuth 2.0 Token Exchange Grant to + * represent the principal in a composite token (e.g. the "delegation" use case). * * @author Steve Riesenberg * @since 1.3 @@ -39,7 +39,8 @@ public class OAuth2TokenExchangeCompositeAuthenticationToken extends AbstractAut private final List actors; - public OAuth2TokenExchangeCompositeAuthenticationToken(Authentication subject, List actors) { + public OAuth2TokenExchangeCompositeAuthenticationToken(Authentication subject, + List actors) { super(subject != null ? subject.getAuthorities() : null); Assert.notNull(subject, "subject cannot be null"); Assert.notNull(actors, "actors cannot be null"); @@ -72,8 +73,8 @@ public class OAuth2TokenExchangeCompositeAuthenticationToken extends AbstractAut if (!(obj instanceof OAuth2TokenExchangeCompositeAuthenticationToken other)) { return false; } - return super.equals(obj) && Objects.equals(this.subject, other.subject) && - Objects.equals(this.actors, other.actors); + return super.equals(obj) && Objects.equals(this.subject, other.subject) + && Objects.equals(this.actors, other.actors); } @Override diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/X509ClientCertificateAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/X509ClientCertificateAuthenticationProvider.java index a5ba5b75..799516ae 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/X509ClientCertificateAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/X509ClientCertificateAuthenticationProvider.java @@ -37,9 +37,10 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** - * An {@link AuthenticationProvider} implementation used for OAuth 2.0 Client Authentication, - * which authenticates the client {@code X509Certificate} received - * when the {@code tls_client_auth} or {@code self_signed_tls_client_auth} authentication method is used. + * An {@link AuthenticationProvider} implementation used for OAuth 2.0 Client + * Authentication, which authenticates the client {@code X509Certificate} received when + * the {@code tls_client_auth} or {@code self_signed_tls_client_auth} authentication + * method is used. * * @author Joe Grandja * @since 1.3 @@ -49,17 +50,22 @@ import org.springframework.util.StringUtils; * @see OAuth2AuthorizationService */ public final class X509ClientCertificateAuthenticationProvider implements AuthenticationProvider { + private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1"; + private final Log logger = LogFactory.getLog(getClass()); + private final RegisteredClientRepository registeredClientRepository; + private final CodeVerifierAuthenticator codeVerifierAuthenticator; - private final Consumer selfSignedCertificateVerifier = - new X509SelfSignedCertificateVerifier(); + + private final Consumer selfSignedCertificateVerifier = new X509SelfSignedCertificateVerifier(); + private Consumer certificateVerifier = this::verifyX509Certificate; /** - * Constructs a {@code X509ClientCertificateAuthenticationProvider} using the provided parameters. - * + * Constructs a {@code X509ClientCertificateAuthenticationProvider} using the provided + * parameters. * @param registeredClientRepository the repository of registered clients * @param authorizationService the authorization service */ @@ -73,11 +79,11 @@ public final class X509ClientCertificateAuthenticationProvider implements Authen @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { - OAuth2ClientAuthenticationToken clientAuthentication = - (OAuth2ClientAuthenticationToken) authentication; + OAuth2ClientAuthenticationToken clientAuthentication = (OAuth2ClientAuthenticationToken) authentication; - if (!ClientAuthenticationMethod.TLS_CLIENT_AUTH.equals(clientAuthentication.getClientAuthenticationMethod()) && - !ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH.equals(clientAuthentication.getClientAuthenticationMethod())) { + if (!ClientAuthenticationMethod.TLS_CLIENT_AUTH.equals(clientAuthentication.getClientAuthenticationMethod()) + && !ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH + .equals(clientAuthentication.getClientAuthenticationMethod())) { return null; } @@ -91,8 +97,8 @@ public final class X509ClientCertificateAuthenticationProvider implements Authen this.logger.trace("Retrieved registered client"); } - if (!registeredClient.getClientAuthenticationMethods().contains( - clientAuthentication.getClientAuthenticationMethod())) { + if (!registeredClient.getClientAuthenticationMethods() + .contains(clientAuthentication.getClientAuthenticationMethod())) { throwInvalidClient("authentication_method"); } @@ -100,17 +106,18 @@ public final class X509ClientCertificateAuthenticationProvider implements Authen throwInvalidClient("credentials"); } - OAuth2ClientAuthenticationContext authenticationContext = - OAuth2ClientAuthenticationContext.with(clientAuthentication) - .registeredClient(registeredClient) - .build(); + OAuth2ClientAuthenticationContext authenticationContext = OAuth2ClientAuthenticationContext + .with(clientAuthentication) + .registeredClient(registeredClient) + .build(); this.certificateVerifier.accept(authenticationContext); if (this.logger.isTraceEnabled()) { this.logger.trace("Validated client authentication parameters"); } - // Validate the "code_verifier" parameter for the confidential client, if available + // Validate the "code_verifier" parameter for the confidential client, if + // available this.codeVerifierAuthenticator.authenticateIfAvailable(clientAuthentication, registeredClient); if (this.logger.isTraceEnabled()) { @@ -127,15 +134,20 @@ public final class X509ClientCertificateAuthenticationProvider implements Authen } /** - * Sets the {@code Consumer} providing access to the {@link OAuth2ClientAuthenticationContext} - * and is responsible for verifying the client {@code X509Certificate} associated in the {@link OAuth2ClientAuthenticationToken}. - * The default implementation for the {@code tls_client_auth} authentication method - * verifies the {@link ClientSettings#getX509CertificateSubjectDN() expected subject distinguished name}. + * Sets the {@code Consumer} providing access to the + * {@link OAuth2ClientAuthenticationContext} and is responsible for verifying the + * client {@code X509Certificate} associated in the + * {@link OAuth2ClientAuthenticationToken}. The default implementation for the + * {@code tls_client_auth} authentication method verifies the + * {@link ClientSettings#getX509CertificateSubjectDN() expected subject distinguished + * name}. * *

- * NOTE: If verification fails, an {@link OAuth2AuthenticationException} MUST be thrown. - * - * @param certificateVerifier the {@code Consumer} providing access to the {@link OAuth2ClientAuthenticationContext} and is responsible for verifying the client {@code X509Certificate} + * NOTE: If verification fails, an {@link OAuth2AuthenticationException} MUST + * be thrown. + * @param certificateVerifier the {@code Consumer} providing access to the + * {@link OAuth2ClientAuthenticationContext} and is responsible for verifying the + * client {@code X509Certificate} */ public void setCertificateVerifier(Consumer certificateVerifier) { Assert.notNull(certificateVerifier, "certificateVerifier cannot be null"); @@ -144,9 +156,11 @@ public final class X509ClientCertificateAuthenticationProvider implements Authen private void verifyX509Certificate(OAuth2ClientAuthenticationContext clientAuthenticationContext) { OAuth2ClientAuthenticationToken clientAuthentication = clientAuthenticationContext.getAuthentication(); - if (ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH.equals(clientAuthentication.getClientAuthenticationMethod())) { + if (ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH + .equals(clientAuthentication.getClientAuthenticationMethod())) { this.selfSignedCertificateVerifier.accept(clientAuthenticationContext); - } else { + } + else { verifyX509CertificateSubjectDN(clientAuthenticationContext); } } @@ -157,8 +171,8 @@ public final class X509ClientCertificateAuthenticationProvider implements Authen X509Certificate[] clientCertificateChain = (X509Certificate[]) clientAuthentication.getCredentials(); X509Certificate clientCertificate = clientCertificateChain[0]; String expectedSubjectDN = registeredClient.getClientSettings().getX509CertificateSubjectDN(); - if (!StringUtils.hasText(expectedSubjectDN) || - !clientCertificate.getSubjectX500Principal().getName().equals(expectedSubjectDN)) { + if (!StringUtils.hasText(expectedSubjectDN) + || !clientCertificate.getSubjectX500Principal().getName().equals(expectedSubjectDN)) { throwInvalidClient("x509_certificate_subject_dn"); } } @@ -168,11 +182,8 @@ public final class X509ClientCertificateAuthenticationProvider implements Authen } private static void throwInvalidClient(String parameterName, Throwable cause) { - OAuth2Error error = new OAuth2Error( - OAuth2ErrorCodes.INVALID_CLIENT, - "Client authentication failed: " + parameterName, - ERROR_URI - ); + OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_CLIENT, + "Client authentication failed: " + parameterName, ERROR_URI); throw new OAuth2AuthenticationException(error, error.toString(), cause); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/X509SelfSignedCertificateVerifier.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/X509SelfSignedCertificateVerifier.java index de57a5d0..cad5d567 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/X509SelfSignedCertificateVerifier.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/X509SelfSignedCertificateVerifier.java @@ -52,15 +52,20 @@ import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; /** - * The default {@code X509Certificate} verifier for the {@code self_signed_tls_client_auth} authentication method. + * The default {@code X509Certificate} verifier for the + * {@code self_signed_tls_client_auth} authentication method. * * @author Joe Grandja * @since 1.3 * @see X509ClientCertificateAuthenticationProvider#setCertificateVerifier(Consumer) */ final class X509SelfSignedCertificateVerifier implements Consumer { + private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-3.2.1"; - private static final JWKMatcher HAS_X509_CERT_CHAIN_MATCHER = new JWKMatcher.Builder().hasX509CertChain(true).build(); + + private static final JWKMatcher HAS_X509_CERT_CHAIN_MATCHER = new JWKMatcher.Builder().hasX509CertChain(true) + .build(); + private final Function jwkSetSupplier = new JwkSetSupplier(); @Override @@ -98,17 +103,17 @@ final class X509SelfSignedCertificateVerifier implements Consumer { + private static final MediaType APPLICATION_JWK_SET_JSON = new MediaType("application", "jwk-set+json"); + private final RestOperations restOperations; + private final Map> jwkSets = new ConcurrentHashMap<>(); private JwkSetSupplier() { @@ -120,13 +125,12 @@ final class X509SelfSignedCertificateVerifier implements Consumer jwkSetSupplier = this.jwkSets.computeIfAbsent( - registeredClient.getId(), (key) -> { - if (!StringUtils.hasText(registeredClient.getClientSettings().getJwkSetUrl())) { - throwInvalidClient("client_jwk_set_url"); - } - return new JwkSetHolder(registeredClient.getClientSettings().getJwkSetUrl()); - }); + Supplier jwkSetSupplier = this.jwkSets.computeIfAbsent(registeredClient.getId(), (key) -> { + if (!StringUtils.hasText(registeredClient.getClientSettings().getJwkSetUrl())) { + throwInvalidClient("client_jwk_set_url"); + } + return new JwkSetHolder(registeredClient.getClientSettings().getJwkSetUrl()); + }); return jwkSetSupplier.get(); } @@ -134,7 +138,8 @@ final class X509SelfSignedCertificateVerifier implements Consumer response = null; try { response = this.restOperations.exchange(request, String.class); - } catch (Exception ex) { + } + catch (Exception ex) { throwInvalidClient("jwk_set_response_error", ex); } if (response.getStatusCode().value() != 200) { @@ -154,7 +160,8 @@ final class X509SelfSignedCertificateVerifier implements Consumer { + private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); + private final Clock clock = Clock.systemUTC(); + private final String jwkSetUrl; + private JWKSet jwkSet; + private Instant lastUpdatedAt; private JwkSetHolder(String jwkSetUrl) { @@ -184,22 +196,24 @@ final class X509SelfSignedCertificateVerifier implements Consumer endpointUris; private IssuerResolver(AuthorizationServerSettings authorizationServerSettings) { if (authorizationServerSettings.getIssuer() != null) { this.issuer = authorizationServerSettings.getIssuer(); this.endpointUris = Collections.emptySet(); - } else { + } + else { this.issuer = null; this.endpointUris = new HashSet<>(); this.endpointUris.add("/.well-known/oauth-authorization-server"); @@ -102,7 +106,8 @@ final class AuthorizationServerContextFilter extends OncePerRequestFilter { String path = request.getRequestURI(); if (!StringUtils.hasText(path)) { path = ""; - } else { + } + else { for (String endpointUri : this.endpointUris) { if (path.contains(endpointUri)) { path = path.replace(endpointUri, ""); @@ -124,10 +129,13 @@ final class AuthorizationServerContextFilter extends OncePerRequestFilter { } private static final class DefaultAuthorizationServerContext implements AuthorizationServerContext { + private final String issuer; + private final AuthorizationServerSettings authorizationServerSettings; - private DefaultAuthorizationServerContext(String issuer, AuthorizationServerSettings authorizationServerSettings) { + private DefaultAuthorizationServerContext(String issuer, + AuthorizationServerSettings authorizationServerSettings) { this.issuer = issuer; this.authorizationServerSettings = authorizationServerSettings; } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/DefaultOAuth2TokenCustomizers.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/DefaultOAuth2TokenCustomizers.java index d970c092..1a6c8441 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/DefaultOAuth2TokenCustomizers.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/DefaultOAuth2TokenCustomizers.java @@ -54,13 +54,14 @@ final class DefaultOAuth2TokenCustomizers { private static void customize(OAuth2TokenContext tokenContext, Map claims) { // Add 'cnf' claim for Mutual-TLS Client Certificate-Bound Access Tokens - if (OAuth2TokenType.ACCESS_TOKEN.equals(tokenContext.getTokenType()) && - tokenContext.getAuthorizationGrant() != null && - tokenContext.getAuthorizationGrant().getPrincipal() instanceof OAuth2ClientAuthenticationToken clientAuthentication) { + if (OAuth2TokenType.ACCESS_TOKEN.equals(tokenContext.getTokenType()) + && tokenContext.getAuthorizationGrant() != null && tokenContext.getAuthorizationGrant() + .getPrincipal() instanceof OAuth2ClientAuthenticationToken clientAuthentication) { - if ((ClientAuthenticationMethod.TLS_CLIENT_AUTH.equals(clientAuthentication.getClientAuthenticationMethod()) || - ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH.equals(clientAuthentication.getClientAuthenticationMethod())) && - tokenContext.getRegisteredClient().getTokenSettings().isX509CertificateBoundAccessTokens()) { + if ((ClientAuthenticationMethod.TLS_CLIENT_AUTH.equals(clientAuthentication.getClientAuthenticationMethod()) + || ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH + .equals(clientAuthentication.getClientAuthenticationMethod())) + && tokenContext.getRegisteredClient().getTokenSettings().isX509CertificateBoundAccessTokens()) { X509Certificate[] clientCertificateChain = (X509Certificate[]) clientAuthentication.getCredentials(); try { @@ -68,7 +69,8 @@ final class DefaultOAuth2TokenCustomizers { Map x5tClaim = new HashMap<>(); x5tClaim.put("x5t#S256", sha256Thumbprint); claims.put("cnf", x5tClaim); - } catch (Exception ex) { + } + catch (Exception ex) { OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, "Failed to compute SHA-256 Thumbprint for client X509Certificate.", null); throw new OAuth2AuthenticationException(error, ex); @@ -77,8 +79,10 @@ final class DefaultOAuth2TokenCustomizers { } // Add 'act' claim for delegation use case of Token Exchange Grant. - // If more than one actor is present, we create a chain of delegation by nesting "act" claims. - if (tokenContext.getPrincipal() instanceof OAuth2TokenExchangeCompositeAuthenticationToken compositeAuthenticationToken) { + // If more than one actor is present, we create a chain of delegation by nesting + // "act" claims. + if (tokenContext + .getPrincipal() instanceof OAuth2TokenExchangeCompositeAuthenticationToken compositeAuthenticationToken) { Map currentClaims = claims; for (OAuth2TokenExchangeActor actor : compositeAuthenticationToken.getActors()) { Map actorClaims = actor.getClaims(); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationEndpointConfigurer.java index 39f16d21..b0462d4d 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationEndpointConfigurer.java @@ -236,10 +236,11 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String authorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getAuthorizationEndpoint()) : - authorizationServerSettings.getAuthorizationEndpoint(); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String authorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getAuthorizationEndpoint()) + : authorizationServerSettings.getAuthorizationEndpoint(); this.requestMatcher = new OrRequestMatcher( new AntPathRequestMatcher(authorizationEndpointUri, HttpMethod.GET.name()), new AntPathRequestMatcher(authorizationEndpointUri, HttpMethod.POST.name())); @@ -256,12 +257,13 @@ public final class OAuth2AuthorizationEndpointConfigurer extends AbstractOAuth2C @Override void configure(HttpSecurity httpSecurity) { AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String authorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getAuthorizationEndpoint()) : - authorizationServerSettings.getAuthorizationEndpoint(); - OAuth2AuthorizationEndpointFilter authorizationEndpointFilter = - new OAuth2AuthorizationEndpointFilter(authenticationManager, authorizationEndpointUri); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String authorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getAuthorizationEndpoint()) + : authorizationServerSettings.getAuthorizationEndpoint(); + OAuth2AuthorizationEndpointFilter authorizationEndpointFilter = new OAuth2AuthorizationEndpointFilter( + authenticationManager, authorizationEndpointUri); List authenticationConverters = createDefaultAuthenticationConverters(); if (!this.authorizationRequestConverters.isEmpty()) { authenticationConverters.addAll(0, this.authorizationRequestConverters); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java index 2a827ae2..ca0d5688 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java @@ -326,9 +326,9 @@ public final class OAuth2AuthorizationServerConfigurer configurer.init(httpSecurity); requestMatchers.add(configurer.getRequestMatcher()); }); - String jwkSetEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getJwkSetEndpoint()) : - authorizationServerSettings.getJwkSetEndpoint(); + String jwkSetEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getJwkSetEndpoint()) + : authorizationServerSettings.getJwkSetEndpoint(); requestMatchers.add(new AntPathRequestMatcher(jwkSetEndpointUri, HttpMethod.GET.name())); this.endpointsMatcher = new OrRequestMatcher(requestMatchers); @@ -356,12 +356,13 @@ public final class OAuth2AuthorizationServerConfigurer JWKSource jwkSource = OAuth2ConfigurerUtils.getJwkSource(httpSecurity); if (jwkSource != null) { - String jwkSetEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getJwkSetEndpoint()) : - authorizationServerSettings.getJwkSetEndpoint(); - NimbusJwkSetEndpointFilter jwkSetEndpointFilter = - new NimbusJwkSetEndpointFilter(jwkSource, jwkSetEndpointUri); - httpSecurity.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class); + String jwkSetEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getJwkSetEndpoint()) + : authorizationServerSettings.getJwkSetEndpoint(); + NimbusJwkSetEndpointFilter jwkSetEndpointFilter = new NimbusJwkSetEndpointFilter(jwkSource, + jwkSetEndpointUri); + httpSecurity.addFilterBefore(postProcess(jwkSetEndpointFilter), + AbstractPreAuthenticatedProcessingFilter.class); } } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataEndpointConfigurer.java index 875e2885..ddf4fea8 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataEndpointConfigurer.java @@ -74,10 +74,10 @@ public final class OAuth2AuthorizationServerMetadataEndpointConfigurer extends A @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String authorizationServerMetadataEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - "/.well-known/oauth-authorization-server/**" : - "/.well-known/oauth-authorization-server"; + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String authorizationServerMetadataEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? "/.well-known/oauth-authorization-server/**" : "/.well-known/oauth-authorization-server"; this.requestMatcher = new AntPathRequestMatcher(authorizationServerMetadataEndpointUri, HttpMethod.GET.name()); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientAuthenticationConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientAuthenticationConfigurer.java index 94fc22c8..a64fd9b0 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientAuthenticationConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientAuthenticationConfigurer.java @@ -180,21 +180,21 @@ public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Co @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String tokenEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getTokenEndpoint()) : - authorizationServerSettings.getTokenEndpoint(); - String tokenIntrospectionEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()) : - authorizationServerSettings.getTokenIntrospectionEndpoint(); - String tokenRevocationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getTokenRevocationEndpoint()) : - authorizationServerSettings.getTokenRevocationEndpoint(); - String deviceAuthorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()) : - authorizationServerSettings.getDeviceAuthorizationEndpoint(); - this.requestMatcher = new OrRequestMatcher( - new AntPathRequestMatcher(tokenEndpointUri, HttpMethod.POST.name()), + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String tokenEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getTokenEndpoint()) + : authorizationServerSettings.getTokenEndpoint(); + String tokenIntrospectionEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()) + : authorizationServerSettings.getTokenIntrospectionEndpoint(); + String tokenRevocationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getTokenRevocationEndpoint()) + : authorizationServerSettings.getTokenRevocationEndpoint(); + String deviceAuthorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()) + : authorizationServerSettings.getDeviceAuthorizationEndpoint(); + this.requestMatcher = new OrRequestMatcher(new AntPathRequestMatcher(tokenEndpointUri, HttpMethod.POST.name()), new AntPathRequestMatcher(tokenIntrospectionEndpointUri, HttpMethod.POST.name()), new AntPathRequestMatcher(tokenRevocationEndpointUri, HttpMethod.POST.name()), new AntPathRequestMatcher(deviceAuthorizationEndpointUri, HttpMethod.POST.name())); @@ -257,12 +257,12 @@ public final class OAuth2ClientAuthenticationConfigurer extends AbstractOAuth2Co registeredClientRepository, authorizationService); authenticationProviders.add(jwtClientAssertionAuthenticationProvider); - X509ClientCertificateAuthenticationProvider x509ClientCertificateAuthenticationProvider = - new X509ClientCertificateAuthenticationProvider(registeredClientRepository, authorizationService); + X509ClientCertificateAuthenticationProvider x509ClientCertificateAuthenticationProvider = new X509ClientCertificateAuthenticationProvider( + registeredClientRepository, authorizationService); authenticationProviders.add(x509ClientCertificateAuthenticationProvider); - ClientSecretAuthenticationProvider clientSecretAuthenticationProvider = - new ClientSecretAuthenticationProvider(registeredClientRepository, authorizationService); + ClientSecretAuthenticationProvider clientSecretAuthenticationProvider = new ClientSecretAuthenticationProvider( + registeredClientRepository, authorizationService); PasswordEncoder passwordEncoder = OAuth2ConfigurerUtils.getOptionalBean(httpSecurity, PasswordEncoder.class); if (passwordEncoder != null) { clientSecretAuthenticationProvider.setPasswordEncoder(passwordEncoder); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ConfigurerUtils.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ConfigurerUtils.java index 4b35000b..3be72c05 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ConfigurerUtils.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ConfigurerUtils.java @@ -59,9 +59,7 @@ final class OAuth2ConfigurerUtils { static String withMultipleIssuersPattern(String endpointUri) { Assert.hasText(endpointUri, "endpointUri cannot be empty"); - return endpointUri.startsWith("/") ? - "/**" + endpointUri : - "/**/" + endpointUri; + return endpointUri.startsWith("/") ? "/**" + endpointUri : "/**/" + endpointUri; } static RegisteredClientRepository getRegisteredClientRepository(HttpSecurity httpSecurity) { @@ -168,8 +166,10 @@ final class OAuth2ConfigurerUtils { } private static OAuth2TokenCustomizer getJwtCustomizer(HttpSecurity httpSecurity) { - final OAuth2TokenCustomizer defaultJwtCustomizer = DefaultOAuth2TokenCustomizers.jwtCustomizer(); - ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, JwtEncodingContext.class); + final OAuth2TokenCustomizer defaultJwtCustomizer = DefaultOAuth2TokenCustomizers + .jwtCustomizer(); + ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, + JwtEncodingContext.class); final OAuth2TokenCustomizer jwtCustomizer = getOptionalBean(httpSecurity, type); if (jwtCustomizer == null) { return defaultJwtCustomizer; @@ -181,8 +181,10 @@ final class OAuth2ConfigurerUtils { } private static OAuth2TokenCustomizer getAccessTokenCustomizer(HttpSecurity httpSecurity) { - final OAuth2TokenCustomizer defaultAccessTokenCustomizer = DefaultOAuth2TokenCustomizers.accessTokenCustomizer(); - ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, OAuth2TokenClaimsContext.class); + final OAuth2TokenCustomizer defaultAccessTokenCustomizer = DefaultOAuth2TokenCustomizers + .accessTokenCustomizer(); + ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2TokenCustomizer.class, + OAuth2TokenClaimsContext.class); OAuth2TokenCustomizer accessTokenCustomizer = getOptionalBean(httpSecurity, type); if (accessTokenCustomizer == null) { return defaultAccessTokenCustomizer; diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceAuthorizationEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceAuthorizationEndpointConfigurer.java index b636ed03..75ed18ec 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceAuthorizationEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceAuthorizationEndpointConfigurer.java @@ -197,11 +197,11 @@ public final class OAuth2DeviceAuthorizationEndpointConfigurer extends AbstractO @Override public void init(HttpSecurity builder) { - AuthorizationServerSettings authorizationServerSettings = - OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder); - String deviceAuthorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()) : - authorizationServerSettings.getDeviceAuthorizationEndpoint(); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(builder); + String deviceAuthorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()) + : authorizationServerSettings.getDeviceAuthorizationEndpoint(); this.requestMatcher = new AntPathRequestMatcher(deviceAuthorizationEndpointUri, HttpMethod.POST.name()); List authenticationProviders = createDefaultAuthenticationProviders(builder); @@ -219,11 +219,11 @@ public final class OAuth2DeviceAuthorizationEndpointConfigurer extends AbstractO AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils .getAuthorizationServerSettings(builder); - String deviceAuthorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()) : - authorizationServerSettings.getDeviceAuthorizationEndpoint(); - OAuth2DeviceAuthorizationEndpointFilter deviceAuthorizationEndpointFilter = - new OAuth2DeviceAuthorizationEndpointFilter(authenticationManager, deviceAuthorizationEndpointUri); + String deviceAuthorizationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getDeviceAuthorizationEndpoint()) + : authorizationServerSettings.getDeviceAuthorizationEndpoint(); + OAuth2DeviceAuthorizationEndpointFilter deviceAuthorizationEndpointFilter = new OAuth2DeviceAuthorizationEndpointFilter( + authenticationManager, deviceAuthorizationEndpointUri); List authenticationConverters = createDefaultAuthenticationConverters(); if (!this.deviceAuthorizationRequestConverters.isEmpty()) { diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceVerificationEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceVerificationEndpointConfigurer.java index 589c158d..1ccc95e8 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceVerificationEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceVerificationEndpointConfigurer.java @@ -232,11 +232,11 @@ public final class OAuth2DeviceVerificationEndpointConfigurer extends AbstractOA @Override public void init(HttpSecurity builder) { - AuthorizationServerSettings authorizationServerSettings = - OAuth2ConfigurerUtils.getAuthorizationServerSettings(builder); - String deviceVerificationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getDeviceVerificationEndpoint()) : - authorizationServerSettings.getDeviceVerificationEndpoint(); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(builder); + String deviceVerificationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getDeviceVerificationEndpoint()) + : authorizationServerSettings.getDeviceVerificationEndpoint(); this.requestMatcher = new OrRequestMatcher( new AntPathRequestMatcher(deviceVerificationEndpointUri, HttpMethod.GET.name()), new AntPathRequestMatcher(deviceVerificationEndpointUri, HttpMethod.POST.name())); @@ -256,11 +256,11 @@ public final class OAuth2DeviceVerificationEndpointConfigurer extends AbstractOA AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils .getAuthorizationServerSettings(builder); - String deviceVerificationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getDeviceVerificationEndpoint()) : - authorizationServerSettings.getDeviceVerificationEndpoint(); - OAuth2DeviceVerificationEndpointFilter deviceVerificationEndpointFilter = - new OAuth2DeviceVerificationEndpointFilter(authenticationManager, deviceVerificationEndpointUri); + String deviceVerificationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getDeviceVerificationEndpoint()) + : authorizationServerSettings.getDeviceVerificationEndpoint(); + OAuth2DeviceVerificationEndpointFilter deviceVerificationEndpointFilter = new OAuth2DeviceVerificationEndpointFilter( + authenticationManager, deviceVerificationEndpointUri); List authenticationConverters = createDefaultAuthenticationConverters(); if (!this.deviceVerificationRequestConverters.isEmpty()) { authenticationConverters.addAll(0, this.deviceVerificationRequestConverters); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenEndpointConfigurer.java index 15fd1847..e572f204 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenEndpointConfigurer.java @@ -185,10 +185,11 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String tokenEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getTokenEndpoint()) : - authorizationServerSettings.getTokenEndpoint(); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String tokenEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getTokenEndpoint()) + : authorizationServerSettings.getTokenEndpoint(); this.requestMatcher = new AntPathRequestMatcher(tokenEndpointUri, HttpMethod.POST.name()); List authenticationProviders = createDefaultAuthenticationProviders(httpSecurity); @@ -206,11 +207,11 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils .getAuthorizationServerSettings(httpSecurity); - String tokenEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getTokenEndpoint()) : - authorizationServerSettings.getTokenEndpoint(); - OAuth2TokenEndpointFilter tokenEndpointFilter = - new OAuth2TokenEndpointFilter(authenticationManager, tokenEndpointUri); + String tokenEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getTokenEndpoint()) + : authorizationServerSettings.getTokenEndpoint(); + OAuth2TokenEndpointFilter tokenEndpointFilter = new OAuth2TokenEndpointFilter(authenticationManager, + tokenEndpointUri); List authenticationConverters = createDefaultAuthenticationConverters(); if (!this.accessTokenRequestConverters.isEmpty()) { authenticationConverters.addAll(0, this.accessTokenRequestConverters); @@ -270,8 +271,8 @@ public final class OAuth2TokenEndpointConfigurer extends AbstractOAuth2Configure authorizationService, tokenGenerator); authenticationProviders.add(deviceCodeAuthenticationProvider); - OAuth2TokenExchangeAuthenticationProvider tokenExchangeAuthenticationProvider = - new OAuth2TokenExchangeAuthenticationProvider(authorizationService, tokenGenerator); + OAuth2TokenExchangeAuthenticationProvider tokenExchangeAuthenticationProvider = new OAuth2TokenExchangeAuthenticationProvider( + authorizationService, tokenGenerator); authenticationProviders.add(tokenExchangeAuthenticationProvider); return authenticationProviders; diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionEndpointConfigurer.java index c49d9e9e..4182e954 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionEndpointConfigurer.java @@ -180,10 +180,11 @@ public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOA @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String tokenIntrospectionEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()) : - authorizationServerSettings.getTokenIntrospectionEndpoint(); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String tokenIntrospectionEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()) + : authorizationServerSettings.getTokenIntrospectionEndpoint(); this.requestMatcher = new AntPathRequestMatcher(tokenIntrospectionEndpointUri, HttpMethod.POST.name()); List authenticationProviders = createDefaultAuthenticationProviders(httpSecurity); @@ -198,12 +199,13 @@ public final class OAuth2TokenIntrospectionEndpointConfigurer extends AbstractOA @Override void configure(HttpSecurity httpSecurity) { AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManager.class); - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String tokenIntrospectionEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()) : - authorizationServerSettings.getTokenIntrospectionEndpoint(); - OAuth2TokenIntrospectionEndpointFilter introspectionEndpointFilter = - new OAuth2TokenIntrospectionEndpointFilter(authenticationManager, tokenIntrospectionEndpointUri); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String tokenIntrospectionEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getTokenIntrospectionEndpoint()) + : authorizationServerSettings.getTokenIntrospectionEndpoint(); + OAuth2TokenIntrospectionEndpointFilter introspectionEndpointFilter = new OAuth2TokenIntrospectionEndpointFilter( + authenticationManager, tokenIntrospectionEndpointUri); List authenticationConverters = createDefaultAuthenticationConverters(); if (!this.introspectionRequestConverters.isEmpty()) { authenticationConverters.addAll(0, this.introspectionRequestConverters); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenRevocationEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenRevocationEndpointConfigurer.java index 88d1f6bf..bb1ed7e4 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenRevocationEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenRevocationEndpointConfigurer.java @@ -179,10 +179,11 @@ public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String tokenRevocationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getTokenRevocationEndpoint()) : - authorizationServerSettings.getTokenRevocationEndpoint(); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String tokenRevocationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getTokenRevocationEndpoint()) + : authorizationServerSettings.getTokenRevocationEndpoint(); this.requestMatcher = new AntPathRequestMatcher(tokenRevocationEndpointUri, HttpMethod.POST.name()); List authenticationProviders = createDefaultAuthenticationProviders(httpSecurity); @@ -200,11 +201,11 @@ public final class OAuth2TokenRevocationEndpointConfigurer extends AbstractOAuth AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils .getAuthorizationServerSettings(httpSecurity); - String tokenRevocationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getTokenRevocationEndpoint()) : - authorizationServerSettings.getTokenRevocationEndpoint(); - OAuth2TokenRevocationEndpointFilter revocationEndpointFilter = - new OAuth2TokenRevocationEndpointFilter(authenticationManager, tokenRevocationEndpointUri); + String tokenRevocationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getTokenRevocationEndpoint()) + : authorizationServerSettings.getTokenRevocationEndpoint(); + OAuth2TokenRevocationEndpointFilter revocationEndpointFilter = new OAuth2TokenRevocationEndpointFilter( + authenticationManager, tokenRevocationEndpointUri); List authenticationConverters = createDefaultAuthenticationConverters(); if (!this.revocationRequestConverters.isEmpty()) { authenticationConverters.addAll(0, this.revocationRequestConverters); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationEndpointConfigurer.java index bd6b4c86..8fad6589 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationEndpointConfigurer.java @@ -190,10 +190,11 @@ public final class OidcClientRegistrationEndpointConfigurer extends AbstractOAut @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String clientRegistrationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getOidcClientRegistrationEndpoint()) : - authorizationServerSettings.getOidcClientRegistrationEndpoint(); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String clientRegistrationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getOidcClientRegistrationEndpoint()) + : authorizationServerSettings.getOidcClientRegistrationEndpoint(); this.requestMatcher = new OrRequestMatcher( new AntPathRequestMatcher(clientRegistrationEndpointUri, HttpMethod.POST.name()), new AntPathRequestMatcher(clientRegistrationEndpointUri, HttpMethod.GET.name())); @@ -213,11 +214,11 @@ public final class OidcClientRegistrationEndpointConfigurer extends AbstractOAut AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils .getAuthorizationServerSettings(httpSecurity); - String clientRegistrationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getOidcClientRegistrationEndpoint()) : - authorizationServerSettings.getOidcClientRegistrationEndpoint(); - OidcClientRegistrationEndpointFilter oidcClientRegistrationEndpointFilter = - new OidcClientRegistrationEndpointFilter(authenticationManager, clientRegistrationEndpointUri); + String clientRegistrationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getOidcClientRegistrationEndpoint()) + : authorizationServerSettings.getOidcClientRegistrationEndpoint(); + OidcClientRegistrationEndpointFilter oidcClientRegistrationEndpointFilter = new OidcClientRegistrationEndpointFilter( + authenticationManager, clientRegistrationEndpointUri); List authenticationConverters = createDefaultAuthenticationConverters(); if (!this.clientRegistrationRequestConverters.isEmpty()) { authenticationConverters.addAll(0, this.clientRegistrationRequestConverters); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcLogoutEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcLogoutEndpointConfigurer.java index a753d1b5..bf4cba5b 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcLogoutEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcLogoutEndpointConfigurer.java @@ -165,14 +165,13 @@ public final class OidcLogoutEndpointConfigurer extends AbstractOAuth2Configurer @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String logoutEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getOidcLogoutEndpoint()) : - authorizationServerSettings.getOidcLogoutEndpoint(); - this.requestMatcher = new OrRequestMatcher( - new AntPathRequestMatcher(logoutEndpointUri, HttpMethod.GET.name()), - new AntPathRequestMatcher(logoutEndpointUri, HttpMethod.POST.name()) - ); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String logoutEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getOidcLogoutEndpoint()) + : authorizationServerSettings.getOidcLogoutEndpoint(); + this.requestMatcher = new OrRequestMatcher(new AntPathRequestMatcher(logoutEndpointUri, HttpMethod.GET.name()), + new AntPathRequestMatcher(logoutEndpointUri, HttpMethod.POST.name())); List authenticationProviders = createDefaultAuthenticationProviders(httpSecurity); if (!this.authenticationProviders.isEmpty()) { @@ -189,11 +188,11 @@ public final class OidcLogoutEndpointConfigurer extends AbstractOAuth2Configurer AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils .getAuthorizationServerSettings(httpSecurity); - String logoutEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getOidcLogoutEndpoint()) : - authorizationServerSettings.getOidcLogoutEndpoint(); - OidcLogoutEndpointFilter oidcLogoutEndpointFilter = - new OidcLogoutEndpointFilter(authenticationManager, logoutEndpointUri); + String logoutEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getOidcLogoutEndpoint()) + : authorizationServerSettings.getOidcLogoutEndpoint(); + OidcLogoutEndpointFilter oidcLogoutEndpointFilter = new OidcLogoutEndpointFilter(authenticationManager, + logoutEndpointUri); List authenticationConverters = createDefaultAuthenticationConverters(); if (!this.logoutRequestConverters.isEmpty()) { authenticationConverters.addAll(0, this.logoutRequestConverters); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationEndpointConfigurer.java index 0ca70ff1..e6b2bf4b 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationEndpointConfigurer.java @@ -74,10 +74,10 @@ public final class OidcProviderConfigurationEndpointConfigurer extends AbstractO @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String oidcProviderConfigurationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - "/**/.well-known/openid-configuration" : - "/.well-known/openid-configuration"; + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String oidcProviderConfigurationEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? "/**/.well-known/openid-configuration" : "/.well-known/openid-configuration"; this.requestMatcher = new AntPathRequestMatcher(oidcProviderConfigurationEndpointUri, HttpMethod.GET.name()); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoEndpointConfigurer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoEndpointConfigurer.java index 4bf8a083..c8c36045 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoEndpointConfigurer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoEndpointConfigurer.java @@ -208,10 +208,11 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur @Override void init(HttpSecurity httpSecurity) { - AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity); - String userInfoEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getOidcUserInfoEndpoint()) : - authorizationServerSettings.getOidcUserInfoEndpoint(); + AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils + .getAuthorizationServerSettings(httpSecurity); + String userInfoEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getOidcUserInfoEndpoint()) + : authorizationServerSettings.getOidcUserInfoEndpoint(); this.requestMatcher = new OrRequestMatcher( new AntPathRequestMatcher(userInfoEndpointUri, HttpMethod.GET.name()), new AntPathRequestMatcher(userInfoEndpointUri, HttpMethod.POST.name())); @@ -231,11 +232,11 @@ public final class OidcUserInfoEndpointConfigurer extends AbstractOAuth2Configur AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils .getAuthorizationServerSettings(httpSecurity); - String userInfoEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() ? - withMultipleIssuersPattern(authorizationServerSettings.getOidcUserInfoEndpoint()) : - authorizationServerSettings.getOidcUserInfoEndpoint(); - OidcUserInfoEndpointFilter oidcUserInfoEndpointFilter = - new OidcUserInfoEndpointFilter(authenticationManager, userInfoEndpointUri); + String userInfoEndpointUri = authorizationServerSettings.isMultipleIssuersAllowed() + ? withMultipleIssuersPattern(authorizationServerSettings.getOidcUserInfoEndpoint()) + : authorizationServerSettings.getOidcUserInfoEndpoint(); + OidcUserInfoEndpointFilter oidcUserInfoEndpointFilter = new OidcUserInfoEndpointFilter(authenticationManager, + userInfoEndpointUri); List authenticationConverters = createDefaultAuthenticationConverters(); if (!this.userInfoRequestConverters.isEmpty()) { authenticationConverters.addAll(0, this.userInfoRequestConverters); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/context/AuthorizationServerContext.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/context/AuthorizationServerContext.java index 7003df6c..64c3f1bc 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/context/AuthorizationServerContext.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/context/AuthorizationServerContext.java @@ -32,18 +32,24 @@ public interface AuthorizationServerContext { * resolves the issuer identifier from the "current" request. * *

- * The issuer identifier may contain a path component to support {@link AuthorizationServerSettings#isMultipleIssuersAllowed() multiple issuers per host} in a multi-tenant hosting configuration. + * The issuer identifier may contain a path component to support + * {@link AuthorizationServerSettings#isMultipleIssuersAllowed() multiple issuers per + * host} in a multi-tenant hosting configuration. * *

* For example: *

    - *
  • {@code https://example.com/issuer1/oauth2/token} — resolves the issuer to {@code https://example.com/issuer1}
  • - *
  • {@code https://example.com/issuer2/oauth2/token} — resolves the issuer to {@code https://example.com/issuer2}
  • - *
  • {@code https://example.com/authz/issuer1/oauth2/token} — resolves the issuer to {@code https://example.com/authz/issuer1}
  • - *
  • {@code https://example.com/authz/issuer2/oauth2/token} — resolves the issuer to {@code https://example.com/authz/issuer2}
  • + *
  • {@code https://example.com/issuer1/oauth2/token} — resolves the issuer to + * {@code https://example.com/issuer1}
  • + *
  • {@code https://example.com/issuer2/oauth2/token} — resolves the issuer to + * {@code https://example.com/issuer2}
  • + *
  • {@code https://example.com/authz/issuer1/oauth2/token} — resolves the + * issuer to {@code https://example.com/authz/issuer1}
  • + *
  • {@code https://example.com/authz/issuer2/oauth2/token} — resolves the + * issuer to {@code https://example.com/authz/issuer2}
  • *
- * - * @return {@link AuthorizationServerSettings#getIssuer()} if available, otherwise, resolves the issuer identifier from the "current" request + * @return {@link AuthorizationServerSettings#getIssuer()} if available, otherwise, + * resolves the issuer identifier from the "current" request */ String getIssuer(); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2TokenExchangeCompositeAuthenticationTokenMixin.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2TokenExchangeCompositeAuthenticationTokenMixin.java index 82ef287f..be55f312 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2TokenExchangeCompositeAuthenticationTokenMixin.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2TokenExchangeCompositeAuthenticationTokenMixin.java @@ -28,7 +28,8 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeCompositeAuthenticationToken; /** - * This mixin class is used to serialize/deserialize {@link OAuth2TokenExchangeCompositeAuthenticationToken}. + * This mixin class is used to serialize/deserialize + * {@link OAuth2TokenExchangeCompositeAuthenticationToken}. * * @author Steve Riesenberg * @since 1.3 diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcAuthenticationProviderUtils.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcAuthenticationProviderUtils.java index 5e8eb3c6..ea9cf087 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcAuthenticationProviderUtils.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcAuthenticationProviderUtils.java @@ -67,11 +67,11 @@ final class OidcAuthenticationProviderUtils { static OAuth2AccessToken accessToken(OAuth2Authorization.Builder builder, T token, OAuth2TokenContext accessTokenContext) { - OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, - token.getTokenValue(), token.getIssuedAt(), token.getExpiresAt(), - accessTokenContext.getAuthorizedScopes()); - OAuth2TokenFormat accessTokenFormat = accessTokenContext.getRegisteredClient().getTokenSettings() - .getAccessTokenFormat(); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, token.getTokenValue(), + token.getIssuedAt(), token.getExpiresAt(), accessTokenContext.getAuthorizedScopes()); + OAuth2TokenFormat accessTokenFormat = accessTokenContext.getRegisteredClient() + .getTokenSettings() + .getAccessTokenFormat(); builder.token(accessToken, (metadata) -> { if (token instanceof ClaimAccessor claimAccessor) { metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, claimAccessor.getClaims()); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java index 1a4360cc..556964cf 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java @@ -63,9 +63,11 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques private static final String DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI = "/.well-known/openid-configuration"; private final RequestMatcher requestMatcher = createRequestMatcher(); - private final OidcProviderConfigurationHttpMessageConverter providerConfigurationHttpMessageConverter = - new OidcProviderConfigurationHttpMessageConverter(); - private Consumer providerConfigurationCustomizer = (providerConfiguration) -> {}; + + private final OidcProviderConfigurationHttpMessageConverter providerConfigurationHttpMessageConverter = new OidcProviderConfigurationHttpMessageConverter(); + + private Consumer providerConfigurationCustomizer = (providerConfiguration) -> { + }; /** * Sets the {@code Consumer} providing access to the @@ -96,29 +98,29 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques .getAuthorizationServerSettings(); OidcProviderConfiguration.Builder providerConfiguration = OidcProviderConfiguration.builder() - .issuer(issuer) - .authorizationEndpoint(asUrl(issuer, authorizationServerSettings.getAuthorizationEndpoint())) - .deviceAuthorizationEndpoint(asUrl(issuer, authorizationServerSettings.getDeviceAuthorizationEndpoint())) - .tokenEndpoint(asUrl(issuer, authorizationServerSettings.getTokenEndpoint())) - .tokenEndpointAuthenticationMethods(clientAuthenticationMethods()) - .jwkSetUrl(asUrl(issuer, authorizationServerSettings.getJwkSetEndpoint())) - .userInfoEndpoint(asUrl(issuer, authorizationServerSettings.getOidcUserInfoEndpoint())) - .endSessionEndpoint(asUrl(issuer, authorizationServerSettings.getOidcLogoutEndpoint())) - .responseType(OAuth2AuthorizationResponseType.CODE.getValue()) - .grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()) - .grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) - .grantType(AuthorizationGrantType.REFRESH_TOKEN.getValue()) - .grantType(AuthorizationGrantType.DEVICE_CODE.getValue()) - .grantType(AuthorizationGrantType.TOKEN_EXCHANGE.getValue()) - .tokenRevocationEndpoint(asUrl(issuer, authorizationServerSettings.getTokenRevocationEndpoint())) - .tokenRevocationEndpointAuthenticationMethods(clientAuthenticationMethods()) - .tokenIntrospectionEndpoint(asUrl(issuer, authorizationServerSettings.getTokenIntrospectionEndpoint())) - .tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods()) - .codeChallengeMethod("S256") - .tlsClientCertificateBoundAccessTokens(true) - .subjectType("public") - .idTokenSigningAlgorithm(SignatureAlgorithm.RS256.getName()) - .scope(OidcScopes.OPENID); + .issuer(issuer) + .authorizationEndpoint(asUrl(issuer, authorizationServerSettings.getAuthorizationEndpoint())) + .deviceAuthorizationEndpoint(asUrl(issuer, authorizationServerSettings.getDeviceAuthorizationEndpoint())) + .tokenEndpoint(asUrl(issuer, authorizationServerSettings.getTokenEndpoint())) + .tokenEndpointAuthenticationMethods(clientAuthenticationMethods()) + .jwkSetUrl(asUrl(issuer, authorizationServerSettings.getJwkSetEndpoint())) + .userInfoEndpoint(asUrl(issuer, authorizationServerSettings.getOidcUserInfoEndpoint())) + .endSessionEndpoint(asUrl(issuer, authorizationServerSettings.getOidcLogoutEndpoint())) + .responseType(OAuth2AuthorizationResponseType.CODE.getValue()) + .grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()) + .grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) + .grantType(AuthorizationGrantType.REFRESH_TOKEN.getValue()) + .grantType(AuthorizationGrantType.DEVICE_CODE.getValue()) + .grantType(AuthorizationGrantType.TOKEN_EXCHANGE.getValue()) + .tokenRevocationEndpoint(asUrl(issuer, authorizationServerSettings.getTokenRevocationEndpoint())) + .tokenRevocationEndpointAuthenticationMethods(clientAuthenticationMethods()) + .tokenIntrospectionEndpoint(asUrl(issuer, authorizationServerSettings.getTokenIntrospectionEndpoint())) + .tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods()) + .codeChallengeMethod("S256") + .tlsClientCertificateBoundAccessTokens(true) + .subjectType("public") + .idTokenSigningAlgorithm(SignatureAlgorithm.RS256.getName()) + .scope(OidcScopes.OPENID); this.providerConfigurationCustomizer.accept(providerConfiguration); @@ -132,10 +134,10 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI, HttpMethod.GET.name()); final RequestMatcher multipleIssuersRequestMatcher = new AntPathRequestMatcher( "/**" + DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI, HttpMethod.GET.name()); - return (request) -> - AuthorizationServerContextHolder.getContext().getAuthorizationServerSettings().isMultipleIssuersAllowed() ? - multipleIssuersRequestMatcher.matches(request) : - defaultRequestMatcher.matches(request); + return (request) -> AuthorizationServerContextHolder.getContext() + .getAuthorizationServerSettings() + .isMultipleIssuersAllowed() ? multipleIssuersRequestMatcher.matches(request) + : defaultRequestMatcher.matches(request); } private static Consumer> clientAuthenticationMethods() { diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettings.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettings.java index 0684adcd..feb95cdb 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettings.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettings.java @@ -44,8 +44,9 @@ public final class AuthorizationServerSettings extends AbstractSettings { } /** - * Returns {@code true} if multiple issuers are allowed per host. The default is {@code false}. - * Using path components in the URL of the issuer identifier enables supporting multiple issuers per host in a multi-tenant hosting configuration. + * Returns {@code true} if multiple issuers are allowed per host. The default is + * {@code false}. Using path components in the URL of the issuer identifier enables + * supporting multiple issuers per host in a multi-tenant hosting configuration. * *

* For example: @@ -53,8 +54,8 @@ public final class AuthorizationServerSettings extends AbstractSettings { *

  • {@code https://example.com/issuer1}
  • *
  • {@code https://example.com/authz/issuer2}
  • * - * - * @return {@code true} if multiple issuers are allowed per host, {@code false} otherwise + * @return {@code true} if multiple issuers are allowed per host, {@code false} + * otherwise * @since 1.3 * @see AuthorizationServerContext#getIssuer() */ @@ -198,8 +199,9 @@ public final class AuthorizationServerSettings extends AbstractSettings { } /** - * Set to {@code true} if multiple issuers are allowed per host. - * Using path components in the URL of the issuer identifier enables supporting multiple issuers per host in a multi-tenant hosting configuration. + * Set to {@code true} if multiple issuers are allowed per host. Using path + * components in the URL of the issuer identifier enables supporting multiple + * issuers per host in a multi-tenant hosting configuration. * *

    * For example: @@ -209,17 +211,20 @@ public final class AuthorizationServerSettings extends AbstractSettings { * * *

    - * NOTE: Explicitly configuring the issuer identifier via {@link #issuer(String)} forces to a single-tenant configuration. - * Avoid configuring the issuer identifier when using a multi-tenant hosting configuration, - * allowing the issuer identifier to be resolved from the "current" request. - * - * @param multipleIssuersAllowed {@code true} if multiple issuers are allowed per host, {@code false} otherwise + * NOTE: Explicitly configuring the issuer identifier via + * {@link #issuer(String)} forces to a single-tenant configuration. Avoid + * configuring the issuer identifier when using a multi-tenant hosting + * configuration, allowing the issuer identifier to be resolved from the + * "current" request. + * @param multipleIssuersAllowed {@code true} if multiple issuers are allowed per + * host, {@code false} otherwise * @return the {@link Builder} for further configuration * @since 1.3 * @see AuthorizationServerContext#getIssuer() */ public Builder multipleIssuersAllowed(boolean multipleIssuersAllowed) { - return setting(ConfigurationSettingNames.AuthorizationServer.MULTIPLE_ISSUERS_ALLOWED, multipleIssuersAllowed); + return setting(ConfigurationSettingNames.AuthorizationServer.MULTIPLE_ISSUERS_ALLOWED, + multipleIssuersAllowed); } /** @@ -328,9 +333,10 @@ public final class AuthorizationServerSettings extends AbstractSettings { @Override public AuthorizationServerSettings build() { AuthorizationServerSettings authorizationServerSettings = new AuthorizationServerSettings(getSettings()); - if (authorizationServerSettings.getIssuer() != null && authorizationServerSettings.isMultipleIssuersAllowed()) { - throw new IllegalArgumentException("The issuer identifier (" + authorizationServerSettings.getIssuer() + - ") cannot be set when isMultipleIssuersAllowed() is true."); + if (authorizationServerSettings.getIssuer() != null + && authorizationServerSettings.isMultipleIssuersAllowed()) { + throw new IllegalArgumentException("The issuer identifier (" + authorizationServerSettings.getIssuer() + + ") cannot be set when isMultipleIssuersAllowed() is true."); } return authorizationServerSettings; } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettings.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettings.java index 8789ecd8..8514e2f3 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettings.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettings.java @@ -81,10 +81,11 @@ public final class ClientSettings extends AbstractSettings { } /** - * Returns the expected subject distinguished name associated to the client {@code X509Certificate} - * received during client authentication when using the {@code tls_client_auth} method. - * - * @return the expected subject distinguished name associated to the client {@code X509Certificate} received during client authentication + * Returns the expected subject distinguished name associated to the client + * {@code X509Certificate} received during client authentication when using the + * {@code tls_client_auth} method. + * @return the expected subject distinguished name associated to the client + * {@code X509Certificate} received during client authentication * @since 1.3 */ public String getX509CertificateSubjectDN() { @@ -168,10 +169,12 @@ public final class ClientSettings extends AbstractSettings { } /** - * Sets the expected subject distinguished name associated to the client {@code X509Certificate} - * received during client authentication when using the {@code tls_client_auth} method. - * - * @param x509CertificateSubjectDN the expected subject distinguished name associated to the client {@code X509Certificate} received during client authentication * @return the {@link Builder} for further configuration + * Sets the expected subject distinguished name associated to the client + * {@code X509Certificate} received during client authentication when using the + * {@code tls_client_auth} method. + * @param x509CertificateSubjectDN the expected subject distinguished name + * associated to the client {@code X509Certificate} received during client + * authentication * @return the {@link Builder} for further configuration * @return the {@link Builder} for further configuration * @since 1.3 */ diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ConfigurationSettingNames.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ConfigurationSettingNames.java index 4139a5a8..9e7f5ca9 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ConfigurationSettingNames.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/ConfigurationSettingNames.java @@ -73,11 +73,13 @@ public final class ConfigurationSettingNames { .concat("token-endpoint-authentication-signing-algorithm"); /** - * Set the expected subject distinguished name associated to the client {@code X509Certificate} - * received during client authentication when using the {@code tls_client_auth} method. + * Set the expected subject distinguished name associated to the client + * {@code X509Certificate} received during client authentication when using the + * {@code tls_client_auth} method. * @since 1.3 */ - public static final String X509_CERTIFICATE_SUBJECT_DN = CLIENT_SETTINGS_NAMESPACE.concat("x509-certificate-subject-dn"); + public static final String X509_CERTIFICATE_SUBJECT_DN = CLIENT_SETTINGS_NAMESPACE + .concat("x509-certificate-subject-dn"); private Client() { } @@ -101,7 +103,8 @@ public final class ConfigurationSettingNames { * Set to {@code true} if multiple issuers are allowed per host. * @since 1.3 */ - public static final String MULTIPLE_ISSUERS_ALLOWED = AUTHORIZATION_SERVER_SETTINGS_NAMESPACE.concat("multiple-issuers-allowed"); + public static final String MULTIPLE_ISSUERS_ALLOWED = AUTHORIZATION_SERVER_SETTINGS_NAMESPACE + .concat("multiple-issuers-allowed"); /** * Set the OAuth 2.0 Authorization endpoint. @@ -221,11 +224,13 @@ public final class ConfigurationSettingNames { .concat("id-token-signature-algorithm"); /** - * Set to {@code true} if access tokens must be bound to the client {@code X509Certificate} - * received during client authentication when using the {@code tls_client_auth} or {@code self_signed_tls_client_auth} method. + * Set to {@code true} if access tokens must be bound to the client + * {@code X509Certificate} received during client authentication when using the + * {@code tls_client_auth} or {@code self_signed_tls_client_auth} method. * @since 1.3 */ - public static final String X509_CERTIFICATE_BOUND_ACCESS_TOKENS = TOKEN_SETTINGS_NAMESPACE.concat("x509-certificate-bound-access-tokens"); + public static final String X509_CERTIFICATE_BOUND_ACCESS_TOKENS = TOKEN_SETTINGS_NAMESPACE + .concat("x509-certificate-bound-access-tokens"); private Token() { } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/TokenSettings.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/TokenSettings.java index e686431a..5ca34056 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/TokenSettings.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/settings/TokenSettings.java @@ -101,11 +101,12 @@ public final class TokenSettings extends AbstractSettings { } /** - * Returns {@code true} if access tokens must be bound to the client {@code X509Certificate} - * received during client authentication when using the {@code tls_client_auth} or {@code self_signed_tls_client_auth} method. - * The default is {@code false}. - * - * @return {@code true} if access tokens must be bound to the client {@code X509Certificate}, {@code false} otherwise + * Returns {@code true} if access tokens must be bound to the client + * {@code X509Certificate} received during client authentication when using the + * {@code tls_client_auth} or {@code self_signed_tls_client_auth} method. The default + * is {@code false}. + * @return {@code true} if access tokens must be bound to the client + * {@code X509Certificate}, {@code false} otherwise * @since 1.3 */ public boolean isX509CertificateBoundAccessTokens() { @@ -117,15 +118,14 @@ public final class TokenSettings extends AbstractSettings { * @return the {@link Builder} */ public static Builder builder() { - return new Builder() - .authorizationCodeTimeToLive(Duration.ofMinutes(5)) - .accessTokenTimeToLive(Duration.ofMinutes(5)) - .accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED) - .deviceCodeTimeToLive(Duration.ofMinutes(5)) - .reuseRefreshTokens(true) - .refreshTokenTimeToLive(Duration.ofMinutes(60)) - .idTokenSignatureAlgorithm(SignatureAlgorithm.RS256) - .x509CertificateBoundAccessTokens(false); + return new Builder().authorizationCodeTimeToLive(Duration.ofMinutes(5)) + .accessTokenTimeToLive(Duration.ofMinutes(5)) + .accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED) + .deviceCodeTimeToLive(Duration.ofMinutes(5)) + .reuseRefreshTokens(true) + .refreshTokenTimeToLive(Duration.ofMinutes(60)) + .idTokenSignatureAlgorithm(SignatureAlgorithm.RS256) + .x509CertificateBoundAccessTokens(false); } /** @@ -237,15 +237,17 @@ public final class TokenSettings extends AbstractSettings { } /** - * Set to {@code true} if access tokens must be bound to the client {@code X509Certificate} - * received during client authentication when using the {@code tls_client_auth} or {@code self_signed_tls_client_auth} method. - * - * @param x509CertificateBoundAccessTokens {@code true} if access tokens must be bound to the client {@code X509Certificate}, {@code false} otherwise + * Set to {@code true} if access tokens must be bound to the client + * {@code X509Certificate} received during client authentication when using the + * {@code tls_client_auth} or {@code self_signed_tls_client_auth} method. + * @param x509CertificateBoundAccessTokens {@code true} if access tokens must be + * bound to the client {@code X509Certificate}, {@code false} otherwise * @return the {@link Builder} for further configuration * @since 1.3 */ public Builder x509CertificateBoundAccessTokens(boolean x509CertificateBoundAccessTokens) { - return setting(ConfigurationSettingNames.Token.X509_CERTIFICATE_BOUND_ACCESS_TOKENS, x509CertificateBoundAccessTokens); + return setting(ConfigurationSettingNames.Token.X509_CERTIFICATE_BOUND_ACCESS_TOKENS, + x509CertificateBoundAccessTokens); } /** diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java index 6c64ee48..043b9b63 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java @@ -61,9 +61,12 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP private static final String DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI = "/.well-known/oauth-authorization-server"; private final RequestMatcher requestMatcher = createRequestMatcher(); - private final OAuth2AuthorizationServerMetadataHttpMessageConverter authorizationServerMetadataHttpMessageConverter = - new OAuth2AuthorizationServerMetadataHttpMessageConverter(); - private Consumer authorizationServerMetadataCustomizer = (authorizationServerMetadata) -> {}; + + private final OAuth2AuthorizationServerMetadataHttpMessageConverter authorizationServerMetadataHttpMessageConverter = new OAuth2AuthorizationServerMetadataHttpMessageConverter(); + + private Consumer authorizationServerMetadataCustomizer = ( + authorizationServerMetadata) -> { + }; /** * Sets the {@code Consumer} providing access to the @@ -93,25 +96,26 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP AuthorizationServerSettings authorizationServerSettings = authorizationServerContext .getAuthorizationServerSettings(); - OAuth2AuthorizationServerMetadata.Builder authorizationServerMetadata = OAuth2AuthorizationServerMetadata.builder() - .issuer(issuer) - .authorizationEndpoint(asUrl(issuer, authorizationServerSettings.getAuthorizationEndpoint())) - .deviceAuthorizationEndpoint(asUrl(issuer, authorizationServerSettings.getDeviceAuthorizationEndpoint())) - .tokenEndpoint(asUrl(issuer, authorizationServerSettings.getTokenEndpoint())) - .tokenEndpointAuthenticationMethods(clientAuthenticationMethods()) - .jwkSetUrl(asUrl(issuer, authorizationServerSettings.getJwkSetEndpoint())) - .responseType(OAuth2AuthorizationResponseType.CODE.getValue()) - .grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()) - .grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) - .grantType(AuthorizationGrantType.REFRESH_TOKEN.getValue()) - .grantType(AuthorizationGrantType.DEVICE_CODE.getValue()) - .grantType(AuthorizationGrantType.TOKEN_EXCHANGE.getValue()) - .tokenRevocationEndpoint(asUrl(issuer, authorizationServerSettings.getTokenRevocationEndpoint())) - .tokenRevocationEndpointAuthenticationMethods(clientAuthenticationMethods()) - .tokenIntrospectionEndpoint(asUrl(issuer, authorizationServerSettings.getTokenIntrospectionEndpoint())) - .tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods()) - .codeChallengeMethod("S256") - .tlsClientCertificateBoundAccessTokens(true); + OAuth2AuthorizationServerMetadata.Builder authorizationServerMetadata = OAuth2AuthorizationServerMetadata + .builder() + .issuer(issuer) + .authorizationEndpoint(asUrl(issuer, authorizationServerSettings.getAuthorizationEndpoint())) + .deviceAuthorizationEndpoint(asUrl(issuer, authorizationServerSettings.getDeviceAuthorizationEndpoint())) + .tokenEndpoint(asUrl(issuer, authorizationServerSettings.getTokenEndpoint())) + .tokenEndpointAuthenticationMethods(clientAuthenticationMethods()) + .jwkSetUrl(asUrl(issuer, authorizationServerSettings.getJwkSetEndpoint())) + .responseType(OAuth2AuthorizationResponseType.CODE.getValue()) + .grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue()) + .grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) + .grantType(AuthorizationGrantType.REFRESH_TOKEN.getValue()) + .grantType(AuthorizationGrantType.DEVICE_CODE.getValue()) + .grantType(AuthorizationGrantType.TOKEN_EXCHANGE.getValue()) + .tokenRevocationEndpoint(asUrl(issuer, authorizationServerSettings.getTokenRevocationEndpoint())) + .tokenRevocationEndpointAuthenticationMethods(clientAuthenticationMethods()) + .tokenIntrospectionEndpoint(asUrl(issuer, authorizationServerSettings.getTokenIntrospectionEndpoint())) + .tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods()) + .codeChallengeMethod("S256") + .tlsClientCertificateBoundAccessTokens(true); this.authorizationServerMetadataCustomizer.accept(authorizationServerMetadata); @@ -125,10 +129,10 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI, HttpMethod.GET.name()); final RequestMatcher multipleIssuersRequestMatcher = new AntPathRequestMatcher( DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI + "/**", HttpMethod.GET.name()); - return (request) -> - AuthorizationServerContextHolder.getContext().getAuthorizationServerSettings().isMultipleIssuersAllowed() ? - multipleIssuersRequestMatcher.matches(request) : - defaultRequestMatcher.matches(request); + return (request) -> AuthorizationServerContextHolder.getContext() + .getAuthorizationServerSettings() + .isMultipleIssuersAllowed() ? multipleIssuersRequestMatcher.matches(request) + : defaultRequestMatcher.matches(request); } private static Consumer> clientAuthenticationMethods() { diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2DeviceAuthorizationEndpointFilter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2DeviceAuthorizationEndpointFilter.java index 1e11628b..ae219070 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2DeviceAuthorizationEndpointFilter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2DeviceAuthorizationEndpointFilter.java @@ -220,8 +220,9 @@ public final class OAuth2DeviceAuthorizationEndpointFilter extends OncePerReques OAuth2UserCode userCode = deviceAuthorizationRequestAuthentication.getUserCode(); // Generate the fully-qualified verification URI - UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(UrlUtils.buildFullRequestUrl(request)) - .replacePath(this.verificationUri); + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder + .fromHttpUrl(UrlUtils.buildFullRequestUrl(request)) + .replacePath(this.verificationUri); String verificationUri = uriComponentsBuilder.build().toUriString(); // @formatter:off String verificationUriComplete = uriComponentsBuilder 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 77643aea..a9886e71 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 @@ -104,10 +104,12 @@ public final class OAuth2TokenEndpointFilter extends OncePerRequestFilter { private final RequestMatcher tokenEndpointMatcher; - private AuthenticationDetailsSource authenticationDetailsSource = - new WebAuthenticationDetailsSource(); + private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); + private AuthenticationConverter authenticationConverter; + private AuthenticationSuccessHandler authenticationSuccessHandler = new OAuth2AccessTokenResponseAuthenticationSuccessHandler(); + private AuthenticationFailureHandler authenticationFailureHandler = new OAuth2ErrorAuthenticationFailureHandler(); /** diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AccessTokenResponseAuthenticationSuccessHandler.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AccessTokenResponseAuthenticationSuccessHandler.java index 5a29aed2..4455c109 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AccessTokenResponseAuthenticationSuccessHandler.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AccessTokenResponseAuthenticationSuccessHandler.java @@ -44,8 +44,9 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; /** - * An implementation of an {@link AuthenticationSuccessHandler} used for handling an {@link OAuth2AccessTokenAuthenticationToken} - * and returning the {@link OAuth2AccessTokenResponse Access Token Response}. + * An implementation of an {@link AuthenticationSuccessHandler} used for handling an + * {@link OAuth2AccessTokenAuthenticationToken} and returning the + * {@link OAuth2AccessTokenResponse Access Token Response}. * * @author Dmitriy Dubson * @since 1.3 @@ -53,9 +54,11 @@ import org.springframework.util.CollectionUtils; * @see OAuth2AccessTokenResponseHttpMessageConverter */ public final class OAuth2AccessTokenResponseAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + private final Log logger = LogFactory.getLog(getClass()); - private final HttpMessageConverter accessTokenResponseConverter = - new OAuth2AccessTokenResponseHttpMessageConverter(); + + private final HttpMessageConverter accessTokenResponseConverter = new OAuth2AccessTokenResponseHttpMessageConverter(); + private Consumer accessTokenResponseCustomizer; @Override @@ -63,11 +66,12 @@ public final class OAuth2AccessTokenResponseAuthenticationSuccessHandler impleme Authentication authentication) throws IOException, ServletException { if (!(authentication instanceof OAuth2AccessTokenAuthenticationToken accessTokenAuthentication)) { if (this.logger.isErrorEnabled()) { - this.logger.error(Authentication.class.getSimpleName() + " must be of type " + - OAuth2AccessTokenAuthenticationToken.class.getName() + - " but was " + authentication.getClass().getName()); + this.logger.error(Authentication.class.getSimpleName() + " must be of type " + + OAuth2AccessTokenAuthenticationToken.class.getName() + " but was " + + authentication.getClass().getName()); } - OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, "Unable to process the access token response.", null); + OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, + "Unable to process the access token response.", null); throw new OAuth2AuthenticationException(error); } @@ -75,10 +79,9 @@ public final class OAuth2AccessTokenResponseAuthenticationSuccessHandler impleme OAuth2RefreshToken refreshToken = accessTokenAuthentication.getRefreshToken(); Map additionalParameters = accessTokenAuthentication.getAdditionalParameters(); - OAuth2AccessTokenResponse.Builder builder = - OAuth2AccessTokenResponse.withToken(accessToken.getTokenValue()) - .tokenType(accessToken.getTokenType()) - .scopes(accessToken.getScopes()); + OAuth2AccessTokenResponse.Builder builder = OAuth2AccessTokenResponse.withToken(accessToken.getTokenValue()) + .tokenType(accessToken.getTokenType()) + .scopes(accessToken.getScopes()); if (accessToken.getIssuedAt() != null && accessToken.getExpiresAt() != null) { builder.expiresIn(ChronoUnit.SECONDS.between(accessToken.getIssuedAt(), accessToken.getExpiresAt())); } @@ -108,12 +111,15 @@ public final class OAuth2AccessTokenResponseAuthenticationSuccessHandler impleme } /** - * Sets the {@code Consumer} providing access to the {@link OAuth2AccessTokenAuthenticationContext} - * containing an {@link OAuth2AccessTokenResponse.Builder} and additional context information. - * - * @param accessTokenResponseCustomizer the {@code Consumer} providing access to the {@link OAuth2AccessTokenAuthenticationContext} containing an {@link OAuth2AccessTokenResponse.Builder} + * Sets the {@code Consumer} providing access to the + * {@link OAuth2AccessTokenAuthenticationContext} containing an + * {@link OAuth2AccessTokenResponse.Builder} and additional context information. + * @param accessTokenResponseCustomizer the {@code Consumer} providing access to the + * {@link OAuth2AccessTokenAuthenticationContext} containing an + * {@link OAuth2AccessTokenResponse.Builder} */ - public void setAccessTokenResponseCustomizer(Consumer accessTokenResponseCustomizer) { + public void setAccessTokenResponseCustomizer( + Consumer accessTokenResponseCustomizer) { Assert.notNull(accessTokenResponseCustomizer, "accessTokenResponseCustomizer cannot be null"); this.accessTokenResponseCustomizer = accessTokenResponseCustomizer; } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverter.java index d99d3031..dad2e1f5 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverter.java @@ -44,8 +44,10 @@ import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; /** - * Attempts to extract an Access Token Request from {@link HttpServletRequest} for the OAuth 2.0 Token Exchange Grant - * and then converts it to an {@link OAuth2TokenExchangeAuthenticationToken} used for authenticating the authorization grant. + * Attempts to extract an Access Token Request from {@link HttpServletRequest} for the + * OAuth 2.0 Token Exchange Grant and then converts it to an + * {@link OAuth2TokenExchangeAuthenticationToken} used for authenticating the + * authorization grant. * * @author Steve Riesenberg * @since 1.3 @@ -81,9 +83,7 @@ public final class OAuth2TokenExchangeAuthenticationConverter implements Authent if (!CollectionUtils.isEmpty(resources)) { for (String resource : resources) { if (!isValidUri(resource)) { - OAuth2EndpointUtils.throwError( - OAuth2ErrorCodes.INVALID_REQUEST, - OAuth2ParameterNames.RESOURCE, + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.RESOURCE, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } } @@ -94,64 +94,52 @@ public final class OAuth2TokenExchangeAuthenticationConverter implements Authent // scope (OPTIONAL) String scope = parameters.getFirst(OAuth2ParameterNames.SCOPE); - if (StringUtils.hasText(scope) && - parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) { - OAuth2EndpointUtils.throwError( - OAuth2ErrorCodes.INVALID_REQUEST, - OAuth2ParameterNames.SCOPE, + if (StringUtils.hasText(scope) && parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) { + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.SCOPE, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } Set requestedScopes = null; if (StringUtils.hasText(scope)) { - requestedScopes = new HashSet<>( - Arrays.asList(StringUtils.delimitedListToStringArray(scope, " "))); + requestedScopes = new HashSet<>(Arrays.asList(StringUtils.delimitedListToStringArray(scope, " "))); } // requested_token_type (OPTIONAL) String requestedTokenType = parameters.getFirst(OAuth2ParameterNames.REQUESTED_TOKEN_TYPE); if (StringUtils.hasText(requestedTokenType)) { if (parameters.get(OAuth2ParameterNames.REQUESTED_TOKEN_TYPE).size() != 1) { - OAuth2EndpointUtils.throwError( - OAuth2ErrorCodes.INVALID_REQUEST, - OAuth2ParameterNames.REQUESTED_TOKEN_TYPE, - OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, + OAuth2ParameterNames.REQUESTED_TOKEN_TYPE, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } validateTokenType(OAuth2ParameterNames.REQUESTED_TOKEN_TYPE, requestedTokenType); - } else { + } + else { requestedTokenType = ACCESS_TOKEN_TYPE_VALUE; } // subject_token (REQUIRED) String subjectToken = parameters.getFirst(OAuth2ParameterNames.SUBJECT_TOKEN); - if (!StringUtils.hasText(subjectToken) || - parameters.get(OAuth2ParameterNames.SUBJECT_TOKEN).size() != 1) { - OAuth2EndpointUtils.throwError( - OAuth2ErrorCodes.INVALID_REQUEST, - OAuth2ParameterNames.SUBJECT_TOKEN, + if (!StringUtils.hasText(subjectToken) || parameters.get(OAuth2ParameterNames.SUBJECT_TOKEN).size() != 1) { + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.SUBJECT_TOKEN, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } // subject_token_type (REQUIRED) String subjectTokenType = parameters.getFirst(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE); - if (!StringUtils.hasText(subjectTokenType) || - parameters.get(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE).size() != 1) { - OAuth2EndpointUtils.throwError( - OAuth2ErrorCodes.INVALID_REQUEST, - OAuth2ParameterNames.SUBJECT_TOKEN_TYPE, + if (!StringUtils.hasText(subjectTokenType) + || parameters.get(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE).size() != 1) { + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.SUBJECT_TOKEN_TYPE, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); - } else { + } + else { validateTokenType(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE, subjectTokenType); } // actor_token (OPTIONAL, REQUIRED if actor_token_type is provided) String actorToken = parameters.getFirst(OAuth2ParameterNames.ACTOR_TOKEN); - if (StringUtils.hasText(actorToken) && - parameters.get(OAuth2ParameterNames.ACTOR_TOKEN).size() != 1) { - OAuth2EndpointUtils.throwError( - OAuth2ErrorCodes.INVALID_REQUEST, - OAuth2ParameterNames.ACTOR_TOKEN, + if (StringUtils.hasText(actorToken) && parameters.get(OAuth2ParameterNames.ACTOR_TOKEN).size() != 1) { + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.ACTOR_TOKEN, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } @@ -159,9 +147,7 @@ public final class OAuth2TokenExchangeAuthenticationConverter implements Authent String actorTokenType = parameters.getFirst(OAuth2ParameterNames.ACTOR_TOKEN_TYPE); if (StringUtils.hasText(actorTokenType)) { if (parameters.get(OAuth2ParameterNames.ACTOR_TOKEN_TYPE).size() != 1) { - OAuth2EndpointUtils.throwError( - OAuth2ErrorCodes.INVALID_REQUEST, - OAuth2ParameterNames.ACTOR_TOKEN_TYPE, + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.ACTOR_TOKEN_TYPE, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } @@ -169,28 +155,23 @@ public final class OAuth2TokenExchangeAuthenticationConverter implements Authent } if (!StringUtils.hasText(actorToken) && StringUtils.hasText(actorTokenType)) { - OAuth2EndpointUtils.throwError( - OAuth2ErrorCodes.INVALID_REQUEST, - OAuth2ParameterNames.ACTOR_TOKEN, + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.ACTOR_TOKEN, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); - } else if (StringUtils.hasText(actorToken) && !StringUtils.hasText(actorTokenType)) { - OAuth2EndpointUtils.throwError( - OAuth2ErrorCodes.INVALID_REQUEST, - OAuth2ParameterNames.ACTOR_TOKEN_TYPE, + } + else if (StringUtils.hasText(actorToken) && !StringUtils.hasText(actorTokenType)) { + OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.ACTOR_TOKEN_TYPE, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } Map additionalParameters = new HashMap<>(); parameters.forEach((key, value) -> { - if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) && - !key.equals(OAuth2ParameterNames.RESOURCE) && - !key.equals(OAuth2ParameterNames.AUDIENCE) && - !key.equals(OAuth2ParameterNames.REQUESTED_TOKEN_TYPE) && - !key.equals(OAuth2ParameterNames.SUBJECT_TOKEN) && - !key.equals(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE) && - !key.equals(OAuth2ParameterNames.ACTOR_TOKEN) && - !key.equals(OAuth2ParameterNames.ACTOR_TOKEN_TYPE) && - !key.equals(OAuth2ParameterNames.SCOPE)) { + if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) && !key.equals(OAuth2ParameterNames.RESOURCE) + && !key.equals(OAuth2ParameterNames.AUDIENCE) + && !key.equals(OAuth2ParameterNames.REQUESTED_TOKEN_TYPE) + && !key.equals(OAuth2ParameterNames.SUBJECT_TOKEN) + && !key.equals(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE) + && !key.equals(OAuth2ParameterNames.ACTOR_TOKEN) + && !key.equals(OAuth2ParameterNames.ACTOR_TOKEN_TYPE) && !key.equals(OAuth2ParameterNames.SCOPE)) { additionalParameters.put(key, (value.size() == 1) ? value.get(0) : value.toArray(new String[0])); } }); @@ -219,7 +200,8 @@ public final class OAuth2TokenExchangeAuthenticationConverter implements Authent try { URI validUri = new URI(uri); return validUri.isAbsolute() && validUri.getFragment() == null; - } catch (URISyntaxException ex) { + } + catch (URISyntaxException ex) { return false; } } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/X509ClientCertificateAuthenticationConverter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/X509ClientCertificateAuthenticationConverter.java index c78b0b66..0938d574 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/X509ClientCertificateAuthenticationConverter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/X509ClientCertificateAuthenticationConverter.java @@ -33,9 +33,10 @@ import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; /** - * Attempts to extract a client {@code X509Certificate} chain from {@link HttpServletRequest} - * and then converts to an {@link OAuth2ClientAuthenticationToken} used for authenticating the client - * using the {@code tls_client_auth} or {@code self_signed_tls_client_auth} method. + * Attempts to extract a client {@code X509Certificate} chain from + * {@link HttpServletRequest} and then converts to an + * {@link OAuth2ClientAuthenticationToken} used for authenticating the client using the + * {@code tls_client_auth} or {@code self_signed_tls_client_auth} method. * * @author Joe Grandja * @since 1.3 @@ -48,8 +49,8 @@ public final class X509ClientCertificateAuthenticationConverter implements Authe @Nullable @Override public Authentication convert(HttpServletRequest request) { - X509Certificate[] clientCertificateChain = - (X509Certificate[]) request.getAttribute("jakarta.servlet.request.X509Certificate"); + X509Certificate[] clientCertificateChain = (X509Certificate[]) request + .getAttribute("jakarta.servlet.request.X509Certificate"); if (clientCertificateChain == null || clientCertificateChain.length == 0) { return null; } @@ -58,21 +59,18 @@ public final class X509ClientCertificateAuthenticationConverter implements Authe // client_id (REQUIRED) String clientId = parameters.getFirst(OAuth2ParameterNames.CLIENT_ID); - if (!StringUtils.hasText(clientId) || - parameters.get(OAuth2ParameterNames.CLIENT_ID).size() != 1) { + if (!StringUtils.hasText(clientId) || parameters.get(OAuth2ParameterNames.CLIENT_ID).size() != 1) { throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST); } - Map additionalParameters = OAuth2EndpointUtils.getParametersIfMatchesAuthorizationCodeGrantRequest( - request, OAuth2ParameterNames.CLIENT_ID); + Map additionalParameters = OAuth2EndpointUtils + .getParametersIfMatchesAuthorizationCodeGrantRequest(request, OAuth2ParameterNames.CLIENT_ID); - ClientAuthenticationMethod clientAuthenticationMethod = - clientCertificateChain.length == 1 ? - ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH : - ClientAuthenticationMethod.TLS_CLIENT_AUTH; + ClientAuthenticationMethod clientAuthenticationMethod = clientCertificateChain.length == 1 + ? ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH : ClientAuthenticationMethod.TLS_CLIENT_AUTH; - return new OAuth2ClientAuthenticationToken(clientId, clientAuthenticationMethod, - clientCertificateChain, additionalParameters); + return new OAuth2ClientAuthenticationToken(clientId, clientAuthenticationMethod, clientCertificateChain, + additionalParameters); } } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataTests.java index 1d9e7628..cdddf57c 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataTests.java @@ -48,23 +48,23 @@ public class OAuth2AuthorizationServerMetadataTests { @Test public void buildWhenAllClaimsProvidedThenCreated() { OAuth2AuthorizationServerMetadata authorizationServerMetadata = OAuth2AuthorizationServerMetadata.builder() - .issuer("https://example.com") - .authorizationEndpoint("https://example.com/oauth2/authorize") - .tokenEndpoint("https://example.com/oauth2/token") - .tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()) - .jwkSetUrl("https://example.com/oauth2/jwks") - .scope("openid") - .responseType("code") - .grantType("authorization_code") - .grantType("client_credentials") - .tokenRevocationEndpoint("https://example.com/oauth2/revoke") - .tokenRevocationEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()) - .tokenIntrospectionEndpoint("https://example.com/oauth2/introspect") - .tokenIntrospectionEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()) - .codeChallengeMethod("S256") - .tlsClientCertificateBoundAccessTokens(true) - .claim("a-claim", "a-value") - .build(); + .issuer("https://example.com") + .authorizationEndpoint("https://example.com/oauth2/authorize") + .tokenEndpoint("https://example.com/oauth2/token") + .tokenEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()) + .jwkSetUrl("https://example.com/oauth2/jwks") + .scope("openid") + .responseType("code") + .grantType("authorization_code") + .grantType("client_credentials") + .tokenRevocationEndpoint("https://example.com/oauth2/revoke") + .tokenRevocationEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()) + .tokenIntrospectionEndpoint("https://example.com/oauth2/introspect") + .tokenIntrospectionEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()) + .codeChallengeMethod("S256") + .tlsClientCertificateBoundAccessTokens(true) + .claim("a-claim", "a-value") + .build(); assertThat(authorizationServerMetadata.getIssuer()).isEqualTo(url("https://example.com")); assertThat(authorizationServerMetadata.getAuthorizationEndpoint()) diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/TestOAuth2Authorizations.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/TestOAuth2Authorizations.java index 94b52085..d09b82cc 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/TestOAuth2Authorizations.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/TestOAuth2Authorizations.java @@ -92,8 +92,8 @@ public class TestOAuth2Authorizations { .attribute(Principal.class.getName(), new TestingAuthenticationToken("principal", null, "ROLE_A", "ROLE_B")); if (accessToken != null) { - OAuth2RefreshToken refreshToken = new OAuth2RefreshToken( - "refresh-token", Instant.now(), Instant.now().plus(1, ChronoUnit.HOURS)); + OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", Instant.now(), + Instant.now().plus(1, ChronoUnit.HOURS)); builder .token(accessToken, (metadata) -> metadata.putAll(tokenMetadata(registeredClient, accessTokenClaims))) .refreshToken(refreshToken); @@ -102,7 +102,8 @@ public class TestOAuth2Authorizations { return builder; } - private static Map tokenMetadata(RegisteredClient registeredClient, Map tokenClaims) { + private static Map tokenMetadata(RegisteredClient registeredClient, + Map tokenClaims) { Map tokenMetadata = new HashMap<>(); OAuth2TokenFormat accessTokenFormat = registeredClient.getTokenSettings().getAccessTokenFormat(); tokenMetadata.put(OAuth2TokenFormat.class.getName(), accessTokenFormat.getValue()); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AccessTokenAuthenticationContextTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AccessTokenAuthenticationContextTests.java index 1d253043..6ccacc3b 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AccessTokenAuthenticationContextTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AccessTokenAuthenticationContextTests.java @@ -34,39 +34,43 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Dmitriy Dubson */ public class OAuth2AccessTokenAuthenticationContextTests { + private final RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); - private final OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(this.registeredClient).build(); - private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken( - this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret()); - private final OAuth2AccessTokenAuthenticationToken accessTokenAuthenticationToken = - new OAuth2AccessTokenAuthenticationToken(this.registeredClient, this.clientPrincipal, - this.authorization.getAccessToken().getToken(), this.authorization.getRefreshToken().getToken()); + + private final OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(this.registeredClient) + .build(); + + private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(this.registeredClient, + ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret()); + + private final OAuth2AccessTokenAuthenticationToken accessTokenAuthenticationToken = new OAuth2AccessTokenAuthenticationToken( + this.registeredClient, this.clientPrincipal, this.authorization.getAccessToken().getToken(), + this.authorization.getRefreshToken().getToken()); @Test public void withWhenAuthenticationNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> OAuth2AccessTokenAuthenticationContext.with(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authentication cannot be null"); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("authentication cannot be null"); } @Test public void setWhenValueNullThenThrowIllegalArgumentException() { - OAuth2AccessTokenAuthenticationContext.Builder builder = - OAuth2AccessTokenAuthenticationContext.with(this.accessTokenAuthenticationToken); + OAuth2AccessTokenAuthenticationContext.Builder builder = OAuth2AccessTokenAuthenticationContext + .with(this.accessTokenAuthenticationToken); - assertThatThrownBy(() -> builder.accessTokenResponse(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("value cannot be null"); + assertThatThrownBy(() -> builder.accessTokenResponse(null)).isInstanceOf(IllegalArgumentException.class) + .hasMessage("value cannot be null"); } @Test public void buildWhenAllValuesProvidedThenAllValuesAreSet() { - OAuth2AccessTokenResponse.Builder accessTokenResponseBuilder = - OAuth2AccessTokenResponse.withToken(this.accessTokenAuthenticationToken.getAccessToken().getTokenValue()); - OAuth2AccessTokenAuthenticationContext context = - OAuth2AccessTokenAuthenticationContext.with(this.accessTokenAuthenticationToken) - .accessTokenResponse(accessTokenResponseBuilder) - .build(); + OAuth2AccessTokenResponse.Builder accessTokenResponseBuilder = OAuth2AccessTokenResponse + .withToken(this.accessTokenAuthenticationToken.getAccessToken().getTokenValue()); + OAuth2AccessTokenAuthenticationContext context = OAuth2AccessTokenAuthenticationContext + .with(this.accessTokenAuthenticationToken) + .accessTokenResponse(accessTokenResponseBuilder) + .build(); assertThat(context.getAuthentication()).isEqualTo(this.accessTokenAuthenticationToken); assertThat(context.getAccessTokenResponse()).isEqualTo(accessTokenResponseBuilder); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java index a5e8459d..47a6ee73 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationProviderTests.java @@ -146,8 +146,8 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests { @Test public void setAuthorizationConsentRequiredWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authenticationProvider.setAuthorizationConsentRequired(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationConsentRequired cannot be null"); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("authorizationConsentRequired cannot be null"); } @Test @@ -486,23 +486,24 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests { @Test public void authenticateWhenCustomAuthorizationConsentRequiredThenUsed() { @SuppressWarnings("unchecked") - Predicate authorizationConsentRequired = mock(Predicate.class); + Predicate authorizationConsentRequired = mock( + Predicate.class); this.authenticationProvider.setAuthorizationConsentRequired(authorizationConsentRequired); RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); String redirectUri = registeredClient.getRedirectUris().toArray(new String[0])[1]; - OAuth2AuthorizationCodeRequestAuthenticationToken authentication = - new OAuth2AuthorizationCodeRequestAuthenticationToken( - AUTHORIZATION_URI, registeredClient.getClientId(), principal, - redirectUri, STATE, registeredClient.getScopes(), null); + OAuth2AuthorizationCodeRequestAuthenticationToken authentication = new OAuth2AuthorizationCodeRequestAuthenticationToken( + AUTHORIZATION_URI, registeredClient.getClientId(), principal, redirectUri, STATE, + registeredClient.getScopes(), null); - OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = - (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider.authenticate(authentication); + OAuth2AuthorizationCodeRequestAuthenticationToken authenticationResult = (OAuth2AuthorizationCodeRequestAuthenticationToken) this.authenticationProvider + .authenticate(authentication); - assertAuthorizationCodeRequestWithAuthorizationCodeResult(registeredClient, authentication, authenticationResult); + assertAuthorizationCodeRequestWithAuthorizationCodeResult(registeredClient, authentication, + authenticationResult); verify(authorizationConsentRequired).test(any()); } 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 faeff816..fc349d96 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 @@ -145,8 +145,8 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests { @Test public void setAuthenticationValidatorWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authenticationProvider.setAuthenticationValidator(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authenticationValidator cannot be null"); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("authenticationValidator cannot be null"); } @Test @@ -325,10 +325,10 @@ public class OAuth2ClientCredentialsAuthenticationProviderTests { @Test public void authenticateWhenCustomAuthenticationValidatorThenUsed() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient2().build(); - OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken( - registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); - OAuth2ClientCredentialsAuthenticationToken authentication = - new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, registeredClient.getScopes(), null); + OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient, + ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); + OAuth2ClientCredentialsAuthenticationToken authentication = new OAuth2ClientCredentialsAuthenticationToken( + clientPrincipal, registeredClient.getScopes(), null); @SuppressWarnings("unchecked") Consumer authenticationValidator = mock(Consumer.class); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProviderTests.java index 10cad005..b74dd2f5 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProviderTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationProviderTests.java @@ -70,15 +70,24 @@ import static org.mockito.Mockito.when; * @author Steve Riesenberg */ public class OAuth2TokenExchangeAuthenticationProviderTests { - private static final Set RESOURCES = Set.of("https://mydomain.com/resource1", "https://mydomain.com/resource2"); + + private static final Set RESOURCES = Set.of("https://mydomain.com/resource1", + "https://mydomain.com/resource2"); + private static final Set AUDIENCES = Set.of("audience1", "audience2"); + private static final String SUBJECT_TOKEN = "EfYu_0jEL"; + private static final String ACTOR_TOKEN = "JlNE_xR1f"; + private static final String ACCESS_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:access_token"; + private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt"; private OAuth2AuthorizationService authorizationService; + private OAuth2TokenGenerator tokenGenerator; + private OAuth2TokenExchangeAuthenticationProvider authenticationProvider; @BeforeEach @@ -168,7 +177,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenSubjectTokenNotFoundThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient); when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(null); // @formatter:off @@ -187,10 +197,12 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenSubjectTokenNotActiveThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient); OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createExpiredAccessToken(SUBJECT_TOKEN)).build(); + .token(createExpiredAccessToken(SUBJECT_TOKEN)) + .build(); when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(authorization); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) @@ -208,10 +220,12 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenSubjectTokenTypeJwtAndSubjectTokenFormatReferenceThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createJwtRequest(registeredClient); OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(SUBJECT_TOKEN), withTokenFormat(OAuth2TokenFormat.REFERENCE)).build(); + .token(createAccessToken(SUBJECT_TOKEN), withTokenFormat(OAuth2TokenFormat.REFERENCE)) + .build(); when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn(authorization); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) @@ -229,7 +243,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenSubjectPrincipalNullThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient); // @formatter:off OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient) @@ -254,12 +269,14 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenActorTokenNotFoundThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient); OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(SUBJECT_TOKEN)).build(); - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization, (OAuth2Authorization) null); + .token(createAccessToken(SUBJECT_TOKEN)) + .build(); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization, (OAuth2Authorization) null); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) .isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) @@ -277,14 +294,17 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenActorTokenNotActiveThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient); OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(SUBJECT_TOKEN)).build(); + .token(createAccessToken(SUBJECT_TOKEN)) + .build(); OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createExpiredAccessToken(ACTOR_TOKEN)).build(); - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization, actorAuthorization); + .token(createExpiredAccessToken(ACTOR_TOKEN)) + .build(); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization, actorAuthorization); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) .isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) @@ -302,14 +322,17 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenActorTokenTypeJwtAndActorTokenFormatReferenceThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createJwtRequest(registeredClient); OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(SUBJECT_TOKEN), withTokenFormat(OAuth2TokenFormat.SELF_CONTAINED)).build(); + .token(createAccessToken(SUBJECT_TOKEN), withTokenFormat(OAuth2TokenFormat.SELF_CONTAINED)) + .build(); OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(ACTOR_TOKEN), withTokenFormat(OAuth2TokenFormat.REFERENCE)).build(); - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization, actorAuthorization); + .token(createAccessToken(ACTOR_TOKEN), withTokenFormat(OAuth2TokenFormat.REFERENCE)) + .build(); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization, actorAuthorization); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) .isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) @@ -327,7 +350,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenMayActAndActorIssClaimNotAuthorizedThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient); Map authorizedActorClaims = Map.of(OAuth2TokenClaimNames.ISS, "issuer", OAuth2TokenClaimNames.SUB, "actor"); @@ -339,9 +363,10 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { Map actorTokenClaims = Map.of(OAuth2TokenClaimNames.ISS, "invalid-issuer", OAuth2TokenClaimNames.SUB, "actor"); OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(ACTOR_TOKEN), withClaims(actorTokenClaims)).build(); - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization, actorAuthorization); + .token(createAccessToken(ACTOR_TOKEN), withClaims(actorTokenClaims)) + .build(); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization, actorAuthorization); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) .isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) @@ -359,7 +384,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenMayActAndActorSubClaimNotAuthorizedThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient); Map authorizedActorClaims = Map.of(OAuth2TokenClaimNames.ISS, "issuer", OAuth2TokenClaimNames.SUB, "actor"); @@ -371,9 +397,10 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { Map actorTokenClaims = Map.of(OAuth2TokenClaimNames.ISS, "issuer", OAuth2TokenClaimNames.SUB, "invalid-actor"); OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(ACTOR_TOKEN), withClaims(actorTokenClaims)).build(); - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization, actorAuthorization); + .token(createAccessToken(ACTOR_TOKEN), withClaims(actorTokenClaims)) + .build(); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization, actorAuthorization); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) .isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) @@ -391,7 +418,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenMayActAndImpersonationThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createImpersonationRequest(registeredClient); Map authorizedActorClaims = Map.of(OAuth2TokenClaimNames.ISS, "issuer", OAuth2TokenClaimNames.SUB, "actor"); @@ -400,8 +428,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { .token(createAccessToken(SUBJECT_TOKEN), withClaims(Map.of("may_act", authorizedActorClaims))) .build(); // @formatter:on - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) .isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) @@ -418,15 +446,18 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenInvalidScopeInRequestThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient, Set.of("invalid")); OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(SUBJECT_TOKEN)).build(); + .token(createAccessToken(SUBJECT_TOKEN)) + .build(); OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(ACTOR_TOKEN)).build(); - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization, actorAuthorization); + .token(createAccessToken(ACTOR_TOKEN)) + .build(); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization, actorAuthorization); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) .isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) @@ -444,14 +475,18 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenInvalidScopeInSubjectAuthorizationThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient, Set.of()); OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(SUBJECT_TOKEN)).authorizedScopes(Set.of("invalid")).build(); + .token(createAccessToken(SUBJECT_TOKEN)) + .authorizedScopes(Set.of("invalid")) + .build(); OAuth2Authorization actorAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .token(createAccessToken(ACTOR_TOKEN)).build(); - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization, actorAuthorization); + .token(createAccessToken(ACTOR_TOKEN)) + .build(); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization, actorAuthorization); // @formatter:off assertThatExceptionOfType(OAuth2AuthenticationException.class) .isThrownBy(() -> this.authenticationProvider.authenticate(authentication)) @@ -469,7 +504,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenNoActorTokenAndValidTokenExchangeThenReturnAccessTokenForImpersonation() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createImpersonationRequest(registeredClient); TestingAuthenticationToken userPrincipal = new TestingAuthenticationToken("user", null, "ROLE_USER"); // @formatter:off @@ -478,19 +514,19 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { .attribute(Principal.class.getName(), userPrincipal) .build(); // @formatter:on - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization); OAuth2AccessToken accessToken = createAccessToken("token-value"); when(this.tokenGenerator.generate(any(OAuth2TokenContext.class))).thenReturn(accessToken); - OAuth2AccessTokenAuthenticationToken authenticationResult = - (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication); + OAuth2AccessTokenAuthenticationToken authenticationResult = (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider + .authenticate(authentication); assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient); assertThat(authenticationResult.getPrincipal()).isEqualTo(authentication.getPrincipal()); assertThat(authenticationResult.getAccessToken()).isEqualTo(accessToken); assertThat(authenticationResult.getRefreshToken()).isNull(); assertThat(authenticationResult.getAdditionalParameters()).hasSize(1); assertThat(authenticationResult.getAdditionalParameters().get(OAuth2ParameterNames.ISSUED_TOKEN_TYPE)) - .isEqualTo(JWT_TOKEN_TYPE_VALUE); + .isEqualTo(JWT_TOKEN_TYPE_VALUE); ArgumentCaptor authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class); ArgumentCaptor tokenContextCaptor = ArgumentCaptor.forClass(OAuth2TokenContext.class); @@ -521,32 +557,33 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenNoActorTokenAndPreviousActorThenReturnAccessTokenForImpersonation() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createImpersonationRequest(registeredClient); TestingAuthenticationToken userPrincipal = new TestingAuthenticationToken("user", null, "ROLE_USER"); - OAuth2TokenExchangeActor previousActor = new OAuth2TokenExchangeActor(Map.of(OAuth2TokenClaimNames.ISS, "issuer1", - OAuth2TokenClaimNames.SUB, "actor")); - OAuth2TokenExchangeCompositeAuthenticationToken subjectPrincipal = - new OAuth2TokenExchangeCompositeAuthenticationToken(userPrincipal, List.of(previousActor)); + OAuth2TokenExchangeActor previousActor = new OAuth2TokenExchangeActor( + Map.of(OAuth2TokenClaimNames.ISS, "issuer1", OAuth2TokenClaimNames.SUB, "actor")); + OAuth2TokenExchangeCompositeAuthenticationToken subjectPrincipal = new OAuth2TokenExchangeCompositeAuthenticationToken( + userPrincipal, List.of(previousActor)); // @formatter:off OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient) .token(createAccessToken(SUBJECT_TOKEN)) .attribute(Principal.class.getName(), subjectPrincipal) .build(); // @formatter:on - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization); OAuth2AccessToken accessToken = createAccessToken("token-value"); when(this.tokenGenerator.generate(any(OAuth2TokenContext.class))).thenReturn(accessToken); - OAuth2AccessTokenAuthenticationToken authenticationResult = - (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication); + OAuth2AccessTokenAuthenticationToken authenticationResult = (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider + .authenticate(authentication); assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient); assertThat(authenticationResult.getPrincipal()).isEqualTo(authentication.getPrincipal()); assertThat(authenticationResult.getAccessToken()).isEqualTo(accessToken); assertThat(authenticationResult.getRefreshToken()).isNull(); assertThat(authenticationResult.getAdditionalParameters()).hasSize(1); assertThat(authenticationResult.getAdditionalParameters().get(OAuth2ParameterNames.ISSUED_TOKEN_TYPE)) - .isEqualTo(JWT_TOKEN_TYPE_VALUE); + .isEqualTo(JWT_TOKEN_TYPE_VALUE); ArgumentCaptor authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class); ArgumentCaptor tokenContextCaptor = ArgumentCaptor.forClass(OAuth2TokenContext.class); @@ -577,15 +614,16 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { @Test public void authenticateWhenActorTokenAndValidTokenExchangeThenReturnAccessTokenForDelegation() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); OAuth2TokenExchangeAuthenticationToken authentication = createDelegationRequest(registeredClient); TestingAuthenticationToken userPrincipal = new TestingAuthenticationToken("user", null, "ROLE_USER"); - OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(Map.of(OAuth2TokenClaimNames.ISS, "issuer1", - OAuth2TokenClaimNames.SUB, "actor1")); - OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(Map.of(OAuth2TokenClaimNames.ISS, "issuer2", - OAuth2TokenClaimNames.SUB, "actor2")); - OAuth2TokenExchangeCompositeAuthenticationToken subjectPrincipal = - new OAuth2TokenExchangeCompositeAuthenticationToken(userPrincipal, List.of(actor1)); + OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor( + Map.of(OAuth2TokenClaimNames.ISS, "issuer1", OAuth2TokenClaimNames.SUB, "actor1")); + OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor( + Map.of(OAuth2TokenClaimNames.ISS, "issuer2", OAuth2TokenClaimNames.SUB, "actor2")); + OAuth2TokenExchangeCompositeAuthenticationToken subjectPrincipal = new OAuth2TokenExchangeCompositeAuthenticationToken( + userPrincipal, List.of(actor1)); // @formatter:off OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient) .token(createAccessToken(SUBJECT_TOKEN), withClaims(Map.of("may_act", actor2.getClaims()))) @@ -596,19 +634,19 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { .token(createAccessToken(ACTOR_TOKEN), withClaims(actor2.getClaims())) .build(); // @formatter:on - when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))).thenReturn( - subjectAuthorization, actorAuthorization); + when(this.authorizationService.findByToken(anyString(), any(OAuth2TokenType.class))) + .thenReturn(subjectAuthorization, actorAuthorization); OAuth2AccessToken accessToken = createAccessToken("token-value"); when(this.tokenGenerator.generate(any(OAuth2TokenContext.class))).thenReturn(accessToken); - OAuth2AccessTokenAuthenticationToken authenticationResult = - (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider.authenticate(authentication); + OAuth2AccessTokenAuthenticationToken authenticationResult = (OAuth2AccessTokenAuthenticationToken) this.authenticationProvider + .authenticate(authentication); assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient); assertThat(authenticationResult.getPrincipal()).isEqualTo(authentication.getPrincipal()); assertThat(authenticationResult.getAccessToken()).isEqualTo(accessToken); assertThat(authenticationResult.getRefreshToken()).isNull(); assertThat(authenticationResult.getAdditionalParameters()).hasSize(1); assertThat(authenticationResult.getAdditionalParameters().get(OAuth2ParameterNames.ISSUED_TOKEN_TYPE)) - .isEqualTo(JWT_TOKEN_TYPE_VALUE); + .isEqualTo(JWT_TOKEN_TYPE_VALUE); ArgumentCaptor authorizationCaptor = ArgumentCaptor.forClass(OAuth2Authorization.class); ArgumentCaptor tokenContextCaptor = ArgumentCaptor.forClass(OAuth2TokenContext.class); @@ -638,8 +676,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { assertThat(authorization.getAccessToken().getToken()).isEqualTo(accessToken); assertThat(authorization.getRefreshToken()).isNull(); - OAuth2TokenExchangeCompositeAuthenticationToken authorizationPrincipal = - authorization.getAttribute(Principal.class.getName()); + OAuth2TokenExchangeCompositeAuthenticationToken authorizationPrincipal = authorization + .getAttribute(Principal.class.getName()); assertThat(authorizationPrincipal).isNotNull(); assertThat(authorizationPrincipal.getSubject()).isSameAs(subjectPrincipal.getSubject()); assertThat(authorizationPrincipal.getActors()).containsExactly(actor2, actor1); @@ -664,7 +702,8 @@ public class OAuth2TokenExchangeAuthenticationProviderTests { clientPrincipal, ACTOR_TOKEN, ACCESS_TOKEN_TYPE_VALUE, RESOURCES, AUDIENCES, requestedScopes, null); } - private static OAuth2TokenExchangeAuthenticationToken createImpersonationRequest(RegisteredClient registeredClient) { + private static OAuth2TokenExchangeAuthenticationToken createImpersonationRequest( + RegisteredClient registeredClient) { OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, null); return new OAuth2TokenExchangeAuthenticationToken(JWT_TOKEN_TYPE_VALUE, SUBJECT_TOKEN, ACCESS_TOKEN_TYPE_VALUE, diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationTokenTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationTokenTests.java index 3795d7b9..cd45aefe 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationTokenTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeAuthenticationTokenTests.java @@ -35,17 +35,27 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Steve Riesenberg */ public class OAuth2TokenExchangeAuthenticationTokenTests { - private static final Set RESOURCES = Set.of("https://mydomain.com/resource1", "https://mydomain.com/resource2"); + + private static final Set RESOURCES = Set.of("https://mydomain.com/resource1", + "https://mydomain.com/resource2"); + private static final Set AUDIENCES = Set.of("audience1", "audience2"); + private static final String SUBJECT_TOKEN = "EfYu_0jEL"; + private static final String ACTOR_TOKEN = "JlNE_xR1f"; + private static final String ACCESS_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:access_token"; + private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt"; private RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); - private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken( - this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret()); + + private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(this.registeredClient, + ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret()); + private Set scopes = Collections.singleton("scope1"); + private Map additionalParameters = Collections.singletonMap("param1", "value1"); @Test diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeCompositeAuthenticationTokenTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeCompositeAuthenticationTokenTests.java index 99ad0e72..f4ef7b90 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeCompositeAuthenticationTokenTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenExchangeCompositeAuthenticationTokenTests.java @@ -57,8 +57,8 @@ public class OAuth2TokenExchangeCompositeAuthenticationTokenTests { OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(Map.of("claim1", "value1")); OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(Map.of("claim2", "value2")); List actors = List.of(actor1, actor2); - OAuth2TokenExchangeCompositeAuthenticationToken authentication = - new OAuth2TokenExchangeCompositeAuthenticationToken(subject, actors); + OAuth2TokenExchangeCompositeAuthenticationToken authentication = new OAuth2TokenExchangeCompositeAuthenticationToken( + subject, actors); assertThat(authentication.getSubject()).isEqualTo(subject); assertThat(authentication.getActors()).isEqualTo(actors); } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/X509ClientCertificateAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/X509ClientCertificateAuthenticationProviderTests.java index 1bd0004c..c37da3f4 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/X509ClientCertificateAuthenticationProviderTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/X509ClientCertificateAuthenticationProviderTests.java @@ -65,18 +65,27 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ public class X509ClientCertificateAuthenticationProviderTests { - // See RFC 7636: Appendix B. Example for the S256 code_challenge_method + + // See RFC 7636: Appendix B. Example for the S256 code_challenge_method // https://tools.ietf.org/html/rfc7636#appendix-B private static final String S256_CODE_VERIFIER = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"; + private static final String S256_CODE_CHALLENGE = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"; private static final String AUTHORIZATION_CODE = "code"; + private static final OAuth2TokenType AUTHORIZATION_CODE_TOKEN_TYPE = new OAuth2TokenType(OAuth2ParameterNames.CODE); + private JWKSet selfSignedCertificateJwkSet; + private MockWebServer server; + private String clientJwkSetUrl; + private RegisteredClientRepository registeredClientRepository; + private OAuth2AuthorizationService authorizationService; + private X509ClientCertificateAuthenticationProvider authenticationProvider; @BeforeEach @@ -102,8 +111,8 @@ public class X509ClientCertificateAuthenticationProviderTests { this.registeredClientRepository = mock(RegisteredClientRepository.class); this.authorizationService = mock(OAuth2AuthorizationService.class); - this.authenticationProvider = new X509ClientCertificateAuthenticationProvider( - this.registeredClientRepository, this.authorizationService); + this.authenticationProvider = new X509ClientCertificateAuthenticationProvider(this.registeredClientRepository, + this.authorizationService); } @AfterEach @@ -114,22 +123,22 @@ public class X509ClientCertificateAuthenticationProviderTests { @Test public void constructorWhenRegisteredClientRepositoryNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new X509ClientCertificateAuthenticationProvider(null, this.authorizationService)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("registeredClientRepository cannot be null"); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("registeredClientRepository cannot be null"); } @Test public void constructorWhenAuthorizationServiceNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> new X509ClientCertificateAuthenticationProvider(this.registeredClientRepository, null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("authorizationService cannot be null"); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("authorizationService cannot be null"); } @Test public void setCertificateVerifierWhenNullThenThrowIllegalArgumentException() { assertThatThrownBy(() -> this.authenticationProvider.setCertificateVerifier(null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("certificateVerifier cannot be null"); + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("certificateVerifier cannot be null"); } @Test @@ -145,36 +154,36 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId() + "-invalid", ClientAuthenticationMethod.TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null); assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .satisfies(error -> { - assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); - assertThat(error.getDescription()).contains(OAuth2ParameterNames.CLIENT_ID); - }); + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .satisfies(error -> { + assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); + assertThat(error.getDescription()).contains(OAuth2ParameterNames.CLIENT_ID); + }); } @Test public void authenticateWhenUnsupportedClientAuthenticationMethodThenThrowOAuth2AuthenticationException() { RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null); assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .satisfies(error -> { - assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); - assertThat(error.getDescription()).contains("authentication_method"); - }); + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .satisfies(error -> { + assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); + assertThat(error.getDescription()).contains("authentication_method"); + }); } @Test @@ -185,17 +194,17 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH, null, null); assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .satisfies(error -> { - assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); - assertThat(error.getDescription()).contains("credentials"); - }); + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .satisfies(error -> { + assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); + assertThat(error.getDescription()).contains("credentials"); + }); } @Test @@ -211,18 +220,18 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null); assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .satisfies(error -> { - assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); - assertThat(error.getDescription()).contains("x509_certificate_subject_dn"); - }); + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .satisfies(error -> { + assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); + assertThat(error.getDescription()).contains("x509_certificate_subject_dn"); + }); } @Test @@ -238,20 +247,21 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null); - OAuth2ClientAuthenticationToken authenticationResult = - (OAuth2ClientAuthenticationToken) this.authenticationProvider.authenticate(authentication); + OAuth2ClientAuthenticationToken authenticationResult = (OAuth2ClientAuthenticationToken) this.authenticationProvider + .authenticate(authentication); assertThat(authenticationResult.isAuthenticated()).isTrue(); assertThat(authenticationResult.getPrincipal().toString()).isEqualTo(registeredClient.getClientId()); assertThat(authenticationResult.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE); assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient); - assertThat(authenticationResult.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH); + assertThat(authenticationResult.getClientAuthenticationMethod()) + .isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH); } @Test @@ -267,18 +277,19 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); + // PKI Certificate will have different issuer OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH, - TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null); // PKI Certificate will have different issuer + TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, null); assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .satisfies(error -> { - assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); - assertThat(error.getDescription()).contains("x509_certificate_issuer"); - }); + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .satisfies(error -> { + assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); + assertThat(error.getDescription()).contains("x509_certificate_issuer"); + }); } @Test @@ -289,18 +300,18 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE, null); assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .satisfies(error -> { - assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); - assertThat(error.getDescription()).contains("client_jwk_set_url"); - }); + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .satisfies(error -> { + assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); + assertThat(error.getDescription()).contains("client_jwk_set_url"); + }); } @Test @@ -316,18 +327,18 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE, null); assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .satisfies(error -> { - assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); - assertThat(error.getDescription()).contains("jwk_set_uri"); - }); + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .satisfies(error -> { + assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); + assertThat(error.getDescription()).contains("jwk_set_uri"); + }); } @Test @@ -352,7 +363,8 @@ public class X509ClientCertificateAuthenticationProviderTests { } @Test - public void authenticateWhenSelfSignedX509CertificateJwkSetResponseNoMatchingKeysThenThrowOAuth2AuthenticationException() throws Exception { + public void authenticateWhenSelfSignedX509CertificateJwkSetResponseNoMatchingKeysThenThrowOAuth2AuthenticationException() + throws Exception { // @formatter:off X509Certificate pkiCertificate = TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE[0]; RSAKey pkiRSAKey = new RSAKey.Builder((RSAPublicKey) pkiCertificate.getPublicKey()) @@ -396,18 +408,18 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE, null); assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .satisfies(error -> { - assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); - assertThat(error.getDescription()).contains(expectedErrorDescription); - }); + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .satisfies(error -> { + assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.INVALID_CLIENT); + assertThat(error.getDescription()).contains(expectedErrorDescription); + }); } @Test @@ -423,20 +435,22 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2ClientAuthenticationToken authentication = new OAuth2ClientAuthenticationToken( registeredClient.getClientId(), ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE, null); - OAuth2ClientAuthenticationToken authenticationResult = - (OAuth2ClientAuthenticationToken) this.authenticationProvider.authenticate(authentication); + OAuth2ClientAuthenticationToken authenticationResult = (OAuth2ClientAuthenticationToken) this.authenticationProvider + .authenticate(authentication); assertThat(authenticationResult.isAuthenticated()).isTrue(); assertThat(authenticationResult.getPrincipal().toString()).isEqualTo(registeredClient.getClientId()); - assertThat(authenticationResult.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE); + assertThat(authenticationResult.getCredentials()) + .isEqualTo(TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE); assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient); - assertThat(authenticationResult.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH); + assertThat(authenticationResult.getClientAuthenticationMethod()) + .isEqualTo(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH); } @Test @@ -452,13 +466,13 @@ public class X509ClientCertificateAuthenticationProviderTests { .build(); // @formatter:on when(this.registeredClientRepository.findByClientId(eq(registeredClient.getClientId()))) - .thenReturn(registeredClient); + .thenReturn(registeredClient); OAuth2Authorization authorization = TestOAuth2Authorizations - .authorization(registeredClient, createPkceAuthorizationParametersS256()) - .build(); + .authorization(registeredClient, createPkceAuthorizationParametersS256()) + .build(); when(this.authorizationService.findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE))) - .thenReturn(authorization); + .thenReturn(authorization); Map parameters = createPkceTokenParameters(S256_CODE_VERIFIER); @@ -466,15 +480,16 @@ public class X509ClientCertificateAuthenticationProviderTests { registeredClient.getClientId(), ClientAuthenticationMethod.TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE, parameters); - OAuth2ClientAuthenticationToken authenticationResult = - (OAuth2ClientAuthenticationToken) this.authenticationProvider.authenticate(authentication); + OAuth2ClientAuthenticationToken authenticationResult = (OAuth2ClientAuthenticationToken) this.authenticationProvider + .authenticate(authentication); verify(this.authorizationService).findByToken(eq(AUTHORIZATION_CODE), eq(AUTHORIZATION_CODE_TOKEN_TYPE)); assertThat(authenticationResult.isAuthenticated()).isTrue(); assertThat(authenticationResult.getPrincipal().toString()).isEqualTo(registeredClient.getClientId()); assertThat(authenticationResult.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE); assertThat(authenticationResult.getRegisteredClient()).isEqualTo(registeredClient); - assertThat(authenticationResult.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH); + assertThat(authenticationResult.getClientAuthenticationMethod()) + .isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH); } private static Map createPkceAuthorizationParametersS256() { diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/AuthorizationServerContextFilterTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/AuthorizationServerContextFilterTests.java index 17b500ee..91413411 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/AuthorizationServerContextFilterTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/AuthorizationServerContextFilterTests.java @@ -37,10 +37,15 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Joe Grandja */ class AuthorizationServerContextFilterTests { + private static final String SCHEME = "https"; + private static final String HOST = "example.com"; + private static final int PORT = 8443; + private static final String DEFAULT_ISSUER = SCHEME + "://" + HOST + ":" + PORT; + private AuthorizationServerContextFilter filter; @Test @@ -60,17 +65,17 @@ class AuthorizationServerContextFilterTests { @Test public void doFilterWhenCustomEndpointsThenIssuerResolved() throws Exception { AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder() - .authorizationEndpoint("/oauth2/v1/authorize") - .deviceAuthorizationEndpoint("/oauth2/v1/device_authorization") - .deviceVerificationEndpoint("/oauth2/v1/device_verification") - .tokenEndpoint("/oauth2/v1/token") - .jwkSetEndpoint("/oauth2/v1/jwks") - .tokenRevocationEndpoint("/oauth2/v1/revoke") - .tokenIntrospectionEndpoint("/oauth2/v1/introspect") - .oidcClientRegistrationEndpoint("/connect/v1/register") - .oidcUserInfoEndpoint("/v1/userinfo") - .oidcLogoutEndpoint("/connect/v1/logout") - .build(); + .authorizationEndpoint("/oauth2/v1/authorize") + .deviceAuthorizationEndpoint("/oauth2/v1/device_authorization") + .deviceVerificationEndpoint("/oauth2/v1/device_verification") + .tokenEndpoint("/oauth2/v1/token") + .jwkSetEndpoint("/oauth2/v1/jwks") + .tokenRevocationEndpoint("/oauth2/v1/revoke") + .tokenIntrospectionEndpoint("/oauth2/v1/introspect") + .oidcClientRegistrationEndpoint("/connect/v1/register") + .oidcUserInfoEndpoint("/v1/userinfo") + .oidcLogoutEndpoint("/connect/v1/logout") + .build(); this.filter = new AuthorizationServerContextFilter(authorizationServerSettings); String issuerPath = "/issuer2"; @@ -101,8 +106,8 @@ class AuthorizationServerContextFilterTests { MockHttpServletResponse response = new MockHttpServletResponse(); AtomicReference resolvedIssuer = new AtomicReference<>(); - FilterChain filterChain = (req, resp) -> - resolvedIssuer.set(AuthorizationServerContextHolder.getContext().getIssuer()); + FilterChain filterChain = (req, resp) -> resolvedIssuer + .set(AuthorizationServerContextHolder.getContext().getIssuer()); this.filter.doFilter(request, response, filterChain); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/DefaultOAuth2TokenCustomizersTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/DefaultOAuth2TokenCustomizersTests.java index b0d01163..42f53ae1 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/DefaultOAuth2TokenCustomizersTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/DefaultOAuth2TokenCustomizersTests.java @@ -55,9 +55,13 @@ import static org.mockito.Mockito.when; * @author Joe Grandja */ class DefaultOAuth2TokenCustomizersTests { + private static final String ISSUER_1 = "issuer-1"; + private static final String ISSUER_2 = "issuer-2"; + private JwsHeader.Builder jwsHeaderBuilder; + private JwtClaimsSet.Builder jwtClaimsBuilder; @BeforeEach @@ -131,10 +135,10 @@ class DefaultOAuth2TokenCustomizersTests { when(tokenExchangeAuthentication.getAudiences()).thenReturn(Collections.emptySet()); Authentication subject = new TestingAuthenticationToken("subject", null); - OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor(Map.of(JwtClaimNames.ISS, ISSUER_1, - JwtClaimNames.SUB, "actor1")); - OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor(Map.of(JwtClaimNames.ISS, ISSUER_2, - JwtClaimNames.SUB, "actor2")); + OAuth2TokenExchangeActor actor1 = new OAuth2TokenExchangeActor( + Map.of(JwtClaimNames.ISS, ISSUER_1, JwtClaimNames.SUB, "actor1")); + OAuth2TokenExchangeActor actor2 = new OAuth2TokenExchangeActor( + Map.of(JwtClaimNames.ISS, ISSUER_2, JwtClaimNames.SUB, "actor2")); OAuth2TokenExchangeCompositeAuthenticationToken principal = new OAuth2TokenExchangeCompositeAuthenticationToken( subject, List.of(actor1, actor2)); @@ -177,11 +181,10 @@ class DefaultOAuth2TokenCustomizersTests { ) .build(); // @formatter:on - OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken( - registeredClient, ClientAuthenticationMethod.TLS_CLIENT_AUTH, - TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE); - OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication = - new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null); + OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient, + ClientAuthenticationMethod.TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE); + OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication = new OAuth2ClientCredentialsAuthenticationToken( + clientPrincipal, null, null); // @formatter:off JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder) .tokenType(OAuth2TokenType.ACCESS_TOKEN) @@ -215,11 +218,11 @@ class DefaultOAuth2TokenCustomizersTests { ) .build(); // @formatter:on - OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken( - registeredClient, ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH, + OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient, + ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH, TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE); - OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication = - new OAuth2ClientCredentialsAuthenticationToken(clientPrincipal, null, null); + OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication = new OAuth2ClientCredentialsAuthenticationToken( + clientPrincipal, null, null); // @formatter:off JwtEncodingContext tokenContext = JwtEncodingContext.with(this.jwsHeaderBuilder, this.jwtClaimsBuilder) .tokenType(OAuth2TokenType.ACCESS_TOKEN) diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/JwkSetTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/JwkSetTests.java index 492d1878..9524486f 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/JwkSetTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/JwkSetTests.java @@ -82,13 +82,13 @@ public class JwkSetTests { public static void init() { JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK); jwkSource = (jwkSelector, securityContext) -> jwkSelector.select(jwkSet); - db = new EmbeddedDatabaseBuilder() - .generateUniqueName(true) - .setType(EmbeddedDatabaseType.HSQL) - .setScriptEncoding("UTF-8") - .addScript("org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql") - .addScript("org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql") - .build(); + db = new EmbeddedDatabaseBuilder().generateUniqueName(true) + .setType(EmbeddedDatabaseType.HSQL) + .setScriptEncoding("UTF-8") + .addScript("org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql") + .addScript( + "org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql") + .build(); } @AfterEach @@ -188,7 +188,10 @@ public class JwkSetTests { @Bean AuthorizationServerSettings authorizationServerSettings() { - return AuthorizationServerSettings.builder().jwkSetEndpoint("/test/jwks").multipleIssuersAllowed(true).build(); + return AuthorizationServerSettings.builder() + .jwkSetEndpoint("/test/jwks") + .multipleIssuersAllowed(true) + .build(); } } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationCodeGrantTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationCodeGrantTests.java index 65e47fef..10654077 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationCodeGrantTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationCodeGrantTests.java @@ -918,30 +918,33 @@ public class OAuth2AuthorizationCodeGrantTests { String issuer = "https://example.com:8443/issuer1"; - MvcResult mvcResult = this.mvc.perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI)) - .queryParams(getAuthorizationRequestParameters(registeredClient)) - .queryParam(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE) - .queryParam(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256") - .with(user("user"))) - .andExpect(status().is3xxRedirection()) - .andReturn(); + MvcResult mvcResult = this.mvc + .perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI)) + .queryParams(getAuthorizationRequestParameters(registeredClient)) + .queryParam(PkceParameterNames.CODE_CHALLENGE, S256_CODE_CHALLENGE) + .queryParam(PkceParameterNames.CODE_CHALLENGE_METHOD, "S256") + .with(user("user"))) + .andExpect(status().is3xxRedirection()) + .andReturn(); String authorizationCode = extractParameterFromRedirectUri(mvcResult.getResponse().getRedirectedUrl(), "code"); - OAuth2Authorization authorizationCodeAuthorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE); + OAuth2Authorization authorizationCodeAuthorization = this.authorizationService.findByToken(authorizationCode, + AUTHORIZATION_CODE_TOKEN_TYPE); - this.mvc.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI)) + this.mvc + .perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI)) .params(getTokenRequestParameters(registeredClient, authorizationCodeAuthorization)) .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) .param(PkceParameterNames.CODE_VERIFIER, S256_CODE_VERIFIER)) - .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) - .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.access_token").isNotEmpty()) - .andExpect(jsonPath("$.token_type").isNotEmpty()) - .andExpect(jsonPath("$.expires_in").isNotEmpty()) - .andExpect(jsonPath("$.refresh_token").doesNotExist()) - .andExpect(jsonPath("$.scope").isNotEmpty()) - .andReturn(); + .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) + .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.access_token").isNotEmpty()) + .andExpect(jsonPath("$.token_type").isNotEmpty()) + .andExpect(jsonPath("$.expires_in").isNotEmpty()) + .andExpect(jsonPath("$.refresh_token").doesNotExist()) + .andExpect(jsonPath("$.scope").isNotEmpty()) + .andReturn(); ArgumentCaptor tokenContextCaptor = ArgumentCaptor.forClass(OAuth2TokenContext.class); verify(tokenGenerator).generate(tokenContextCaptor.capture()); @@ -1333,7 +1336,8 @@ public class OAuth2AuthorizationCodeGrantTests { @EnableWebSecurity @Import(OAuth2AuthorizationServerConfiguration.class) - static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfigurationWithTokenGenerator { + static class AuthorizationServerConfigurationWithMultipleIssuersAllowed + extends AuthorizationServerConfigurationWithTokenGenerator { @Bean AuthorizationServerSettings authorizationServerSettings() { diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataTests.java index 0b8deb64..9fc78b37 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataTests.java @@ -110,13 +110,14 @@ public class OAuth2AuthorizationServerMetadataTests { this.spring.register(AuthorizationServerConfiguration.class).autowire(); this.mvc.perform(get(ISSUER.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI))) - .andExpect(status().is2xxSuccessful()) - .andExpect(jsonPath("issuer").value(ISSUER)) - .andReturn(); + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("issuer").value(ISSUER)) + .andReturn(); } @Test - public void requestWhenAuthorizationServerMetadataRequestIncludesIssuerPathThenMetadataResponseHasIssuerPath() throws Exception { + public void requestWhenAuthorizationServerMetadataRequestIncludesIssuerPathThenMetadataResponseHasIssuerPath() + throws Exception { this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire(); String host = "https://example.com:8443"; @@ -124,23 +125,23 @@ public class OAuth2AuthorizationServerMetadataTests { String issuerPath = "/issuer1"; String issuer = host.concat(issuerPath); this.mvc.perform(get(host.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI).concat(issuerPath))) - .andExpect(status().is2xxSuccessful()) - .andExpect(jsonPath("issuer").value(issuer)) - .andReturn(); + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("issuer").value(issuer)) + .andReturn(); issuerPath = "/path1/issuer2"; issuer = host.concat(issuerPath); this.mvc.perform(get(host.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI).concat(issuerPath))) - .andExpect(status().is2xxSuccessful()) - .andExpect(jsonPath("issuer").value(issuer)) - .andReturn(); + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("issuer").value(issuer)) + .andReturn(); issuerPath = "/path1/path2/issuer3"; issuer = host.concat(issuerPath); this.mvc.perform(get(host.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI).concat(issuerPath))) - .andExpect(status().is2xxSuccessful()) - .andExpect(jsonPath("issuer").value(issuer)) - .andReturn(); + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("issuer").value(issuer)) + .andReturn(); } // gh-616 @@ -150,9 +151,9 @@ public class OAuth2AuthorizationServerMetadataTests { this.spring.register(AuthorizationServerConfigurationWithMetadataCustomizer.class).autowire(); this.mvc.perform(get(ISSUER.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI))) - .andExpect(status().is2xxSuccessful()) - .andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED, - hasItems("scope1", "scope2"))); + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED, + hasItems("scope1", "scope2"))); } @EnableWebSecurity diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientCredentialsGrantTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientCredentialsGrantTests.java index 72fc98cd..07cd817f 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientCredentialsGrantTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2ClientCredentialsGrantTests.java @@ -298,14 +298,14 @@ public class OAuth2ClientCredentialsGrantTests { // @formatter:on this.registeredClientRepository.save(registeredClient); - this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) - .with(x509(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE)) - .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) - .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) - .param(OAuth2ParameterNames.SCOPE, "scope1 scope2")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.access_token").isNotEmpty()) - .andExpect(jsonPath("$.scope").value("scope1 scope2")); + this.mvc + .perform(post(DEFAULT_TOKEN_ENDPOINT_URI).with(x509(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE)) + .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()) + .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) + .param(OAuth2ParameterNames.SCOPE, "scope1 scope2")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.access_token").isNotEmpty()) + .andExpect(jsonPath("$.scope").value("scope1 scope2")); verify(jwtCustomizer).customize(any()); } @@ -344,13 +344,12 @@ public class OAuth2ClientCredentialsGrantTests { .forClass(List.class); verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture()); List authenticationConverters = authenticationConvertersCaptor.getValue(); - assertThat(authenticationConverters).allMatch((converter) -> - converter == authenticationConverter || - converter instanceof OAuth2AuthorizationCodeAuthenticationConverter || - converter instanceof OAuth2RefreshTokenAuthenticationConverter || - converter instanceof OAuth2ClientCredentialsAuthenticationConverter || - converter instanceof OAuth2DeviceCodeAuthenticationConverter || - converter instanceof OAuth2TokenExchangeAuthenticationConverter); + assertThat(authenticationConverters).allMatch((converter) -> converter == authenticationConverter + || converter instanceof OAuth2AuthorizationCodeAuthenticationConverter + || converter instanceof OAuth2RefreshTokenAuthenticationConverter + || converter instanceof OAuth2ClientCredentialsAuthenticationConverter + || converter instanceof OAuth2DeviceCodeAuthenticationConverter + || converter instanceof OAuth2TokenExchangeAuthenticationConverter); verify(authenticationProvider).authenticate(eq(clientCredentialsAuthentication)); @@ -359,13 +358,12 @@ public class OAuth2ClientCredentialsGrantTests { .forClass(List.class); verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture()); List authenticationProviders = authenticationProvidersCaptor.getValue(); - assertThat(authenticationProviders).allMatch((provider) -> - provider == authenticationProvider || - provider instanceof OAuth2AuthorizationCodeAuthenticationProvider || - provider instanceof OAuth2RefreshTokenAuthenticationProvider || - provider instanceof OAuth2ClientCredentialsAuthenticationProvider || - provider instanceof OAuth2DeviceCodeAuthenticationProvider || - provider instanceof OAuth2TokenExchangeAuthenticationProvider); + assertThat(authenticationProviders).allMatch((provider) -> provider == authenticationProvider + || provider instanceof OAuth2AuthorizationCodeAuthenticationProvider + || provider instanceof OAuth2RefreshTokenAuthenticationProvider + || provider instanceof OAuth2ClientCredentialsAuthenticationProvider + || provider instanceof OAuth2DeviceCodeAuthenticationProvider + || provider instanceof OAuth2TokenExchangeAuthenticationProvider); verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(accessTokenAuthentication)); } @@ -395,13 +393,12 @@ public class OAuth2ClientCredentialsGrantTests { .forClass(List.class); verify(authenticationConvertersConsumer).accept(authenticationConvertersCaptor.capture()); List authenticationConverters = authenticationConvertersCaptor.getValue(); - assertThat(authenticationConverters).allMatch((converter) -> - converter == authenticationConverter || - converter instanceof JwtClientAssertionAuthenticationConverter || - converter instanceof X509ClientCertificateAuthenticationConverter || - converter instanceof ClientSecretBasicAuthenticationConverter || - converter instanceof ClientSecretPostAuthenticationConverter || - converter instanceof PublicClientAuthenticationConverter); + assertThat(authenticationConverters).allMatch((converter) -> converter == authenticationConverter + || converter instanceof JwtClientAssertionAuthenticationConverter + || converter instanceof X509ClientCertificateAuthenticationConverter + || converter instanceof ClientSecretBasicAuthenticationConverter + || converter instanceof ClientSecretPostAuthenticationConverter + || converter instanceof PublicClientAuthenticationConverter); verify(authenticationProvider).authenticate(eq(clientPrincipal)); @@ -410,12 +407,11 @@ public class OAuth2ClientCredentialsGrantTests { .forClass(List.class); verify(authenticationProvidersConsumer).accept(authenticationProvidersCaptor.capture()); List authenticationProviders = authenticationProvidersCaptor.getValue(); - assertThat(authenticationProviders).allMatch((provider) -> - provider == authenticationProvider || - provider instanceof JwtClientAssertionAuthenticationProvider || - provider instanceof X509ClientCertificateAuthenticationProvider || - provider instanceof ClientSecretAuthenticationProvider || - provider instanceof PublicClientAuthenticationProvider); + assertThat(authenticationProviders).allMatch((provider) -> provider == authenticationProvider + || provider instanceof JwtClientAssertionAuthenticationProvider + || provider instanceof X509ClientCertificateAuthenticationProvider + || provider instanceof ClientSecretAuthenticationProvider + || provider instanceof PublicClientAuthenticationProvider); verify(authenticationSuccessHandler).onAuthenticationSuccess(any(), any(), eq(clientPrincipal)); } @@ -429,14 +425,15 @@ public class OAuth2ClientCredentialsGrantTests { String issuer = "https://example.com:8443/issuer1"; - this.mvc.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI)) - .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) - .param(OAuth2ParameterNames.SCOPE, "scope1 scope2") - .header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth( - registeredClient.getClientId(), registeredClient.getClientSecret()))) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.access_token").isNotEmpty()) - .andExpect(jsonPath("$.scope").value("scope1 scope2")); + this.mvc + .perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI)) + .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) + .param(OAuth2ParameterNames.SCOPE, "scope1 scope2") + .header(HttpHeaders.AUTHORIZATION, + "Basic " + encodeBasicAuth(registeredClient.getClientId(), registeredClient.getClientSecret()))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.access_token").isNotEmpty()) + .andExpect(jsonPath("$.scope").value("scope1 scope2")); ArgumentCaptor jwtEncodingContextCaptor = ArgumentCaptor.forClass(JwtEncodingContext.class); verify(jwtCustomizer).customize(jwtEncodingContextCaptor.capture()); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceCodeGrantTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceCodeGrantTests.java index 1a53bbec..8c31ece0 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceCodeGrantTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2DeviceCodeGrantTests.java @@ -247,9 +247,9 @@ public class OAuth2DeviceCodeGrantTests { String userCode = deviceAuthorizationResponse.getUserCode().getTokenValue(); assertThat(userCode).matches("[A-Z]{4}-[A-Z]{4}"); assertThat(deviceAuthorizationResponse.getVerificationUri()) - .isEqualTo("https://example.com:8443/oauth2/device_verification"); + .isEqualTo("https://example.com:8443/oauth2/device_verification"); assertThat(deviceAuthorizationResponse.getVerificationUriComplete()) - .isEqualTo("https://example.com:8443/oauth2/device_verification?user_code=" + userCode); + .isEqualTo("https://example.com:8443/oauth2/device_verification?user_code=" + userCode); String deviceCode = deviceAuthorizationResponse.getDeviceCode().getTokenValue(); OAuth2Authorization authorization = this.authorizationService.findByToken(deviceCode, DEVICE_CODE_TOKEN_TYPE); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenExchangeGrantTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenExchangeGrantTests.java index 8a89c4b3..b9b959cf 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenExchangeGrantTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenExchangeGrantTests.java @@ -94,18 +94,24 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. */ @ExtendWith(SpringTestContextExtension.class) public class OAuth2TokenExchangeGrantTests { + private static final String DEFAULT_TOKEN_ENDPOINT_URI = "/oauth2/token"; + private static final String RESOURCE = "https://mydomain.com/resource"; + private static final String AUDIENCE = "audience"; + private static final String SUBJECT_TOKEN = "EfYu_0jEL"; + private static final String ACTOR_TOKEN = "JlNE_xR1f"; + private static final String ACCESS_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:access_token"; + private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt"; public final SpringTestContext spring = new SpringTestContext(); - private final HttpMessageConverter accessTokenResponseHttpMessageConverter = - new OAuth2AccessTokenResponseHttpMessageConverter(); + private final HttpMessageConverter accessTokenResponseHttpMessageConverter = new OAuth2AccessTokenResponseHttpMessageConverter(); @Autowired private MockMvc mvc; @@ -152,7 +158,8 @@ public class OAuth2TokenExchangeGrantTests { this.spring.register(AuthorizationServerConfiguration.class).autowire(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); this.registeredClientRepository.save(registeredClient); MultiValueMap parameters = new LinkedMultiValueMap<>(); @@ -168,23 +175,27 @@ public class OAuth2TokenExchangeGrantTests { } @Test - public void requestWhenAccessTokenRequestValidAndNoActorTokenThenReturnAccessTokenResponseForImpersonation() throws Exception { + public void requestWhenAccessTokenRequestValidAndNoActorTokenThenReturnAccessTokenResponseForImpersonation() + throws Exception { this.spring.register(AuthorizationServerConfiguration.class).autowire(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); this.registeredClientRepository.save(registeredClient); UsernamePasswordAuthenticationToken userPrincipal = createUserPrincipal("user"); OAuth2Authorization subjectAuthorization = TestOAuth2Authorizations.authorization(registeredClient) - .attribute(Principal.class.getName(), userPrincipal).build(); + .attribute(Principal.class.getName(), userPrincipal) + .build(); this.authorizationService.save(subjectAuthorization); MultiValueMap parameters = new LinkedMultiValueMap<>(); parameters.set(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.TOKEN_EXCHANGE.getValue()); parameters.set(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId()); parameters.set(OAuth2ParameterNames.REQUESTED_TOKEN_TYPE, JWT_TOKEN_TYPE_VALUE); - parameters.set(OAuth2ParameterNames.SUBJECT_TOKEN, subjectAuthorization.getAccessToken().getToken().getTokenValue()); + parameters.set(OAuth2ParameterNames.SUBJECT_TOKEN, + subjectAuthorization.getAccessToken().getToken().getTokenValue()); parameters.set(OAuth2ParameterNames.SUBJECT_TOKEN_TYPE, JWT_TOKEN_TYPE_VALUE); parameters.set(OAuth2ParameterNames.RESOURCE, RESOURCE); parameters.set(OAuth2ParameterNames.AUDIENCE, AUDIENCE); @@ -208,8 +219,8 @@ public class OAuth2TokenExchangeGrantTests { MockHttpServletResponse servletResponse = mvcResult.getResponse(); MockClientHttpResponse httpResponse = new MockClientHttpResponse(servletResponse.getContentAsByteArray(), HttpStatus.OK); - OAuth2AccessTokenResponse accessTokenResponse = - this.accessTokenResponseHttpMessageConverter.read(OAuth2AccessTokenResponse.class, httpResponse); + OAuth2AccessTokenResponse accessTokenResponse = this.accessTokenResponseHttpMessageConverter + .read(OAuth2AccessTokenResponse.class, httpResponse); String accessToken = accessTokenResponse.getAccessToken().getTokenValue(); OAuth2Authorization authorization = this.authorizationService.findByToken(accessToken, @@ -217,19 +228,22 @@ public class OAuth2TokenExchangeGrantTests { assertThat(authorization).isNotNull(); assertThat(authorization.getAccessToken()).isNotNull(); assertThat(authorization.getAccessToken().getClaims()).isNotNull(); - // We do not populate claims (e.g. `aud`) based on the resource or audience parameters + // We do not populate claims (e.g. `aud`) based on the resource or audience + // parameters assertThat(authorization.getAccessToken().getClaims().get(OAuth2TokenClaimNames.AUD)) - .isEqualTo(List.of(registeredClient.getClientId())); + .isEqualTo(List.of(registeredClient.getClientId())); assertThat(authorization.getRefreshToken()).isNull(); assertThat(authorization.getAttribute(Principal.class.getName())).isEqualTo(userPrincipal); } @Test - public void requestWhenAccessTokenRequestValidAndActorTokenThenReturnAccessTokenResponseForDelegation() throws Exception { + public void requestWhenAccessTokenRequestValidAndActorTokenThenReturnAccessTokenResponseForDelegation() + throws Exception { this.spring.register(AuthorizationServerConfiguration.class).autowire(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); this.registeredClientRepository.save(registeredClient); UsernamePasswordAuthenticationToken userPrincipal = createUserPrincipal("user"); @@ -284,8 +298,8 @@ public class OAuth2TokenExchangeGrantTests { MockHttpServletResponse servletResponse = mvcResult.getResponse(); MockClientHttpResponse httpResponse = new MockClientHttpResponse(servletResponse.getContentAsByteArray(), HttpStatus.OK); - OAuth2AccessTokenResponse accessTokenResponse = - this.accessTokenResponseHttpMessageConverter.read(OAuth2AccessTokenResponse.class, httpResponse); + OAuth2AccessTokenResponse accessTokenResponse = this.accessTokenResponseHttpMessageConverter + .read(OAuth2AccessTokenResponse.class, httpResponse); String accessToken = accessTokenResponse.getAccessToken().getTokenValue(); OAuth2Authorization authorization = this.authorizationService.findByToken(accessToken, @@ -296,7 +310,7 @@ public class OAuth2TokenExchangeGrantTests { assertThat(authorization.getAccessToken().getClaims().get("act")).isNotNull(); assertThat(authorization.getRefreshToken()).isNull(); assertThat(authorization.getAttribute(Principal.class.getName())) - .isInstanceOf(OAuth2TokenExchangeCompositeAuthenticationToken.class); + .isInstanceOf(OAuth2TokenExchangeCompositeAuthenticationToken.class); } private static OAuth2AccessToken createAccessToken(String tokenValue) { @@ -363,6 +377,7 @@ public class OAuth2TokenExchangeGrantTests { PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } + } } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionTests.java index 7073b616..7c066e9c 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2TokenIntrospectionTests.java @@ -437,11 +437,10 @@ public class OAuth2TokenIntrospectionTests { OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); - Authentication clientPrincipal = new OAuth2ClientAuthenticationToken( - introspectRegisteredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, introspectRegisteredClient.getClientSecret()); - OAuth2TokenIntrospectionAuthenticationToken tokenIntrospectionAuthentication = - new OAuth2TokenIntrospectionAuthenticationToken( - accessToken.getTokenValue(), clientPrincipal, null, null); + Authentication clientPrincipal = new OAuth2ClientAuthenticationToken(introspectRegisteredClient, + ClientAuthenticationMethod.CLIENT_SECRET_BASIC, introspectRegisteredClient.getClientSecret()); + OAuth2TokenIntrospectionAuthenticationToken tokenIntrospectionAuthentication = new OAuth2TokenIntrospectionAuthenticationToken( + accessToken.getTokenValue(), clientPrincipal, null, null); when(authenticationConverter.convert(any())).thenReturn(tokenIntrospectionAuthentication); when(authenticationProvider.supports(eq(OAuth2TokenIntrospectionAuthenticationToken.class))).thenReturn(true); @@ -600,10 +599,12 @@ public class OAuth2TokenIntrospectionTests { } // @formatter:on - @Override AuthorizationServerSettings authorizationServerSettings() { - return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).tokenIntrospectionEndpoint("/test/introspect").build(); + return AuthorizationServerSettings.builder() + .multipleIssuersAllowed(true) + .tokenIntrospectionEndpoint("/test/introspect") + .build(); } } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationTests.java index 7d830220..74bbf472 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcClientRegistrationTests.java @@ -387,7 +387,8 @@ public class OidcClientRegistrationTests { when(authenticationProvider.authenticate(any())).thenThrow(new OAuth2AuthenticationException("error")); this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_CLIENT_REGISTRATION_ENDPOINT_URI)) - .param(OAuth2ParameterNames.CLIENT_ID, "invalid").with(jwt())); + .param(OAuth2ParameterNames.CLIENT_ID, "invalid") + .with(jwt())); verify(authenticationFailureHandler).onAuthenticationFailure(any(), any(), any()); verifyNoInteractions(authenticationSuccessHandler); @@ -411,14 +412,16 @@ public class OidcClientRegistrationTests { OidcClientRegistration clientRegistrationResponse = registerClient(clientRegistration); - this.mvc.perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI)) - .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) - .param(OAuth2ParameterNames.SCOPE, "scope1") - .with(httpBasic(clientRegistrationResponse.getClientId(), clientRegistrationResponse.getClientSecret()))) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.access_token").isNotEmpty()) - .andExpect(jsonPath("$.scope").value("scope1")) - .andReturn(); + this.mvc + .perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI)) + .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) + .param(OAuth2ParameterNames.SCOPE, "scope1") + .with(httpBasic(clientRegistrationResponse.getClientId(), + clientRegistrationResponse.getClientSecret()))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.access_token").isNotEmpty()) + .andExpect(jsonPath("$.scope").value("scope1")) + .andReturn(); } // gh-1344 @@ -445,12 +448,12 @@ public class OidcClientRegistrationTests { Instant issuedAt = Instant.now(); Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); JwtClaimsSet jwtClaimsSet = JwtClaimsSet.builder() - .issuer(clientRegistrationResponse.getClientId()) - .subject(clientRegistrationResponse.getClientId()) - .audience(Collections.singletonList(asUrl(ISSUER, this.authorizationServerSettings.getTokenEndpoint()))) - .issuedAt(issuedAt) - .expiresAt(expiresAt) - .build(); + .issuer(clientRegistrationResponse.getClientId()) + .subject(clientRegistrationResponse.getClientId()) + .audience(Collections.singletonList(asUrl(ISSUER, this.authorizationServerSettings.getTokenEndpoint()))) + .issuedAt(issuedAt) + .expiresAt(expiresAt) + .build(); JWKSet jwkSet = new JWKSet( TestJwks.jwk(new SecretKeySpec(clientRegistrationResponse.getClientSecret().getBytes(), "HS256")) @@ -460,15 +463,17 @@ public class OidcClientRegistrationTests { Jwt jwtAssertion = jwtClientAssertionEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet)); - this.mvc.perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI)) - .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) - .param(OAuth2ParameterNames.SCOPE, "scope1") - .param(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE, "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") - .param(OAuth2ParameterNames.CLIENT_ASSERTION, jwtAssertion.getTokenValue()) - .param(OAuth2ParameterNames.CLIENT_ID, clientRegistrationResponse.getClientId())) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.access_token").isNotEmpty()) - .andExpect(jsonPath("$.scope").value("scope1")); + this.mvc + .perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI)) + .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) + .param(OAuth2ParameterNames.SCOPE, "scope1") + .param(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE, + "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") + .param(OAuth2ParameterNames.CLIENT_ASSERTION, jwtAssertion.getTokenValue()) + .param(OAuth2ParameterNames.CLIENT_ID, clientRegistrationResponse.getClientId())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.access_token").isNotEmpty()) + .andExpect(jsonPath("$.scope").value("scope1")); } @Test @@ -533,7 +538,8 @@ public class OidcClientRegistrationTests { // @formatter:on Jwt jwtAssertion = jwtClientAssertionEncoder.encode(JwtEncoderParameters.from(jwsHeader, jwtClaimsSet)); - MvcResult mvcResult = this.mvc.perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI)) + MvcResult mvcResult = this.mvc + .perform(post(ISSUER.concat(DEFAULT_TOKEN_ENDPOINT_URI)) .param(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue()) .param(OAuth2ParameterNames.SCOPE, clientRegistrationScope) .param(OAuth2ParameterNames.CLIENT_ASSERTION_TYPE, @@ -553,8 +559,8 @@ public class OidcClientRegistrationTests { httpHeaders.setBearerAuth(accessToken.getTokenValue()); // Register the client - mvcResult = this.mvc.perform(post(ISSUER.concat(DEFAULT_OIDC_CLIENT_REGISTRATION_ENDPOINT_URI)) - .headers(httpHeaders) + mvcResult = this.mvc + .perform(post(ISSUER.concat(DEFAULT_OIDC_CLIENT_REGISTRATION_ENDPOINT_URI)).headers(httpHeaders) .contentType(MediaType.APPLICATION_JSON) .content(getClientRegistrationRequestContent(clientRegistration))) .andExpect(status().isCreated()) @@ -569,11 +575,11 @@ public class OidcClientRegistrationTests { Instant issuedAt = Instant.now(); Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); return JwtClaimsSet.builder() - .issuer(registeredClient.getClientId()) - .subject(registeredClient.getClientId()) - .audience(Collections.singletonList(asUrl(ISSUER, this.authorizationServerSettings.getTokenEndpoint()))) - .issuedAt(issuedAt) - .expiresAt(expiresAt); + .issuer(registeredClient.getClientId()) + .subject(registeredClient.getClientId()) + .audience(Collections.singletonList(asUrl(ISSUER, this.authorizationServerSettings.getTokenEndpoint()))) + .issuedAt(issuedAt) + .expiresAt(expiresAt); } private static String asUrl(String uri, String path) { @@ -753,9 +759,7 @@ public class OidcClientRegistrationTests { @Bean AuthorizationServerSettings authorizationServerSettings() { - return AuthorizationServerSettings.builder() - .multipleIssuersAllowed(true) - .build(); + return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build(); } @Bean diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationTests.java index 71da1153..1d0fbf48 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationTests.java @@ -80,28 +80,29 @@ public class OidcProviderConfigurationTests { this.spring.register(AuthorizationServerConfiguration.class).autowire(); this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))) - .andExpect(status().is2xxSuccessful()) - .andExpectAll(defaultConfigurationMatchers(ISSUER)); + .andExpect(status().is2xxSuccessful()) + .andExpectAll(defaultConfigurationMatchers(ISSUER)); } @Test - public void requestWhenConfigurationRequestIncludesIssuerPathThenConfigurationResponseHasIssuerPath() throws Exception { + public void requestWhenConfigurationRequestIncludesIssuerPathThenConfigurationResponseHasIssuerPath() + throws Exception { this.spring.register(AuthorizationServerConfigurationWithMultipleIssuersAllowed.class).autowire(); String issuer = "https://example.com:8443/issuer1"; this.mvc.perform(get(issuer.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))) - .andExpect(status().is2xxSuccessful()) - .andExpectAll(defaultConfigurationMatchers(issuer)); + .andExpect(status().is2xxSuccessful()) + .andExpectAll(defaultConfigurationMatchers(issuer)); issuer = "https://example.com:8443/path1/issuer2"; this.mvc.perform(get(issuer.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))) - .andExpect(status().is2xxSuccessful()) - .andExpectAll(defaultConfigurationMatchers(issuer)); + .andExpect(status().is2xxSuccessful()) + .andExpectAll(defaultConfigurationMatchers(issuer)); issuer = "https://example.com:8443/path1/path2/issuer3"; this.mvc.perform(get(issuer.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))) - .andExpect(status().is2xxSuccessful()) - .andExpectAll(defaultConfigurationMatchers(issuer)); + .andExpect(status().is2xxSuccessful()) + .andExpectAll(defaultConfigurationMatchers(issuer)); } // gh-632 @@ -109,10 +110,9 @@ public class OidcProviderConfigurationTests { public void requestWhenConfigurationRequestAndUserAuthenticatedThenReturnConfigurationResponse() throws Exception { this.spring.register(AuthorizationServerConfiguration.class).autowire(); - this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)) - .with(user("user"))) - .andExpect(status().is2xxSuccessful()) - .andExpectAll(defaultConfigurationMatchers(ISSUER)); + this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)).with(user("user"))) + .andExpect(status().is2xxSuccessful()) + .andExpectAll(defaultConfigurationMatchers(ISSUER)); } // gh-616 @@ -122,9 +122,9 @@ public class OidcProviderConfigurationTests { this.spring.register(AuthorizationServerConfigurationWithProviderConfigurationCustomizer.class).autowire(); this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))) - .andExpect(status().is2xxSuccessful()) - .andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED, - hasItems(OidcScopes.OPENID, OidcScopes.PROFILE, OidcScopes.EMAIL))); + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath(OAuth2AuthorizationServerMetadataClaimNames.SCOPES_SUPPORTED, + hasItems(OidcScopes.OPENID, OidcScopes.PROFILE, OidcScopes.EMAIL))); } @Test @@ -133,9 +133,10 @@ public class OidcProviderConfigurationTests { this.spring.register(AuthorizationServerConfigurationWithClientRegistrationEnabled.class).autowire(); this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI))) - .andExpect(status().is2xxSuccessful()) - .andExpectAll(defaultConfigurationMatchers(ISSUER)) - .andExpect(jsonPath("$.registration_endpoint").value(ISSUER.concat(this.authorizationServerSettings.getOidcClientRegistrationEndpoint()))); + .andExpect(status().is2xxSuccessful()) + .andExpectAll(defaultConfigurationMatchers(ISSUER)) + .andExpect(jsonPath("$.registration_endpoint") + .value(ISSUER.concat(this.authorizationServerSettings.getOidcClientRegistrationEndpoint()))); } private ResultMatcher[] defaultConfigurationMatchers(String issuer) { @@ -235,9 +236,7 @@ public class OidcProviderConfigurationTests { @Bean AuthorizationServerSettings authorizationServerSettings() { - return AuthorizationServerSettings.builder() - .issuer(ISSUER) - .build(); + return AuthorizationServerSettings.builder().issuer(ISSUER).build(); } } @@ -248,9 +247,7 @@ public class OidcProviderConfigurationTests { @Bean AuthorizationServerSettings authorizationServerSettings() { - return AuthorizationServerSettings.builder() - .multipleIssuersAllowed(true) - .build(); + return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build(); } } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcTests.java index 86b336be..d26e7386 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcTests.java @@ -324,12 +324,13 @@ public class OidcTests { String issuer = "https://example.com:8443/issuer1"; // Login - MultiValueMap authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient); - MvcResult mvcResult = this.mvc.perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI)) - .queryParams(authorizationRequestParameters) - .with(user("user"))) - .andExpect(status().is3xxRedirection()) - .andReturn(); + MultiValueMap authorizationRequestParameters = getAuthorizationRequestParameters( + registeredClient); + MvcResult mvcResult = this.mvc + .perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI)).queryParams(authorizationRequestParameters) + .with(user("user"))) + .andExpect(status().is3xxRedirection()) + .andReturn(); MockHttpSession session = (MockHttpSession) mvcResult.getRequest().getSession(); assertThat(session.isNew()).isTrue(); @@ -340,12 +341,13 @@ public class OidcTests { AUTHORIZATION_CODE_TOKEN_TYPE); // Get ID Token - mvcResult = this.mvc.perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI)) - .params(getTokenRequestParameters(registeredClient, authorization)) - .header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth( - registeredClient.getClientId(), registeredClient.getClientSecret()))) - .andExpect(status().isOk()) - .andReturn(); + mvcResult = this.mvc + .perform(post(issuer.concat(DEFAULT_TOKEN_ENDPOINT_URI)) + .params(getTokenRequestParameters(registeredClient, authorization)) + .header(HttpHeaders.AUTHORIZATION, + "Basic " + encodeBasicAuth(registeredClient.getClientId(), registeredClient.getClientSecret()))) + .andExpect(status().isOk()) + .andReturn(); MockHttpServletResponse servletResponse = mvcResult.getResponse(); MockClientHttpResponse httpResponse = new MockClientHttpResponse(servletResponse.getContentAsByteArray(), @@ -356,11 +358,11 @@ public class OidcTests { String idToken = (String) accessTokenResponse.getAdditionalParameters().get(OidcParameterNames.ID_TOKEN); // Logout - mvcResult = this.mvc.perform(post(issuer.concat(DEFAULT_OIDC_LOGOUT_ENDPOINT_URI)) - .param("id_token_hint", idToken) - .session(session)) - .andExpect(status().is3xxRedirection()) - .andReturn(); + mvcResult = this.mvc + .perform(post(issuer.concat(DEFAULT_OIDC_LOGOUT_ENDPOINT_URI)).param("id_token_hint", idToken) + .session(session)) + .andExpect(status().is3xxRedirection()) + .andReturn(); redirectedUrl = mvcResult.getResponse().getRedirectedUrl(); assertThat(redirectedUrl).matches("/"); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoTests.java index 9d19601f..237abc7c 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcUserInfoTests.java @@ -526,9 +526,7 @@ public class OidcUserInfoTests { @Bean AuthorizationServerSettings authorizationServerSettings() { - return AuthorizationServerSettings.builder() - .multipleIssuersAllowed(true) - .build(); + return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build(); } } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java index 1e636609..95a784f1 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java @@ -63,8 +63,8 @@ public class OidcProviderConfigurationEndpointFilterTests { @Test public void doFilterWhenNotConfigurationRequestThenNotProcessed() throws Exception { - AuthorizationServerContextHolder.setContext( - new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null)); + AuthorizationServerContextHolder + .setContext(new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null)); String requestUri = "/path"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); @@ -79,8 +79,8 @@ public class OidcProviderConfigurationEndpointFilterTests { @Test public void doFilterWhenConfigurationRequestPostThenNotProcessed() throws Exception { - AuthorizationServerContextHolder.setContext( - new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null)); + AuthorizationServerContextHolder + .setContext(new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null)); String requestUri = DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI; MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri); @@ -137,18 +137,25 @@ public class OidcProviderConfigurationEndpointFilterTests { assertThat(providerConfigurationResponse).contains("\"jwks_uri\":\"https://example.com/oauth2/v1/jwks\""); assertThat(providerConfigurationResponse).contains("\"scopes_supported\":[\"openid\"]"); assertThat(providerConfigurationResponse).contains("\"response_types_supported\":[\"code\"]"); - assertThat(providerConfigurationResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\",\"urn:ietf:params:oauth:grant-type:token-exchange\"]"); - assertThat(providerConfigurationResponse).contains("\"revocation_endpoint\":\"https://example.com/oauth2/v1/revoke\""); - assertThat(providerConfigurationResponse).contains("\"revocation_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); - assertThat(providerConfigurationResponse).contains("\"introspection_endpoint\":\"https://example.com/oauth2/v1/introspect\""); - assertThat(providerConfigurationResponse).contains("\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); + assertThat(providerConfigurationResponse).contains( + "\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\",\"urn:ietf:params:oauth:grant-type:token-exchange\"]"); + assertThat(providerConfigurationResponse) + .contains("\"revocation_endpoint\":\"https://example.com/oauth2/v1/revoke\""); + assertThat(providerConfigurationResponse).contains( + "\"revocation_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); + assertThat(providerConfigurationResponse) + .contains("\"introspection_endpoint\":\"https://example.com/oauth2/v1/introspect\""); + assertThat(providerConfigurationResponse).contains( + "\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); assertThat(providerConfigurationResponse).contains("\"code_challenge_methods_supported\":[\"S256\"]"); assertThat(providerConfigurationResponse).contains("\"tls_client_certificate_bound_access_tokens\":true"); assertThat(providerConfigurationResponse).contains("\"subject_types_supported\":[\"public\"]"); assertThat(providerConfigurationResponse).contains("\"id_token_signing_alg_values_supported\":[\"RS256\"]"); assertThat(providerConfigurationResponse).contains("\"userinfo_endpoint\":\"https://example.com/userinfo\""); - assertThat(providerConfigurationResponse).contains("\"end_session_endpoint\":\"https://example.com/connect/logout\""); - assertThat(providerConfigurationResponse).contains("\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); + assertThat(providerConfigurationResponse) + .contains("\"end_session_endpoint\":\"https://example.com/connect/logout\""); + assertThat(providerConfigurationResponse).contains( + "\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); } @Test diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettingsTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettingsTests.java index 31fa6639..50d8aa95 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettingsTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/AuthorizationServerSettingsTests.java @@ -86,13 +86,16 @@ public class AuthorizationServerSettingsTests { public void buildWhenIssuerSetAndMultipleIssuersAllowedTrueThenThrowIllegalArgumentException() { String issuer = "https://example.com:9000"; assertThatIllegalArgumentException() - .isThrownBy(() -> AuthorizationServerSettings.builder().issuer(issuer).multipleIssuersAllowed(true).build()) - .withMessage("The issuer identifier (" + issuer + ") cannot be set when isMultipleIssuersAllowed() is true."); + .isThrownBy(() -> AuthorizationServerSettings.builder().issuer(issuer).multipleIssuersAllowed(true).build()) + .withMessage( + "The issuer identifier (" + issuer + ") cannot be set when isMultipleIssuersAllowed() is true."); } @Test public void buildWhenIssuerNotSetAndMultipleIssuersAllowedTrueThenDefaultsAreSet() { - AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build(); + AuthorizationServerSettings authorizationServerSettings = AuthorizationServerSettings.builder() + .multipleIssuersAllowed(true) + .build(); assertThat(authorizationServerSettings.getIssuer()).isNull(); assertThat(authorizationServerSettings.isMultipleIssuersAllowed()).isTrue(); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettingsTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettingsTests.java index b86d3ab0..327e3cf8 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettingsTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/ClientSettingsTests.java @@ -65,9 +65,10 @@ public class ClientSettingsTests { @Test public void x509CertificateSubjectDNWhenProvidedThenSet() { ClientSettings clientSettings = ClientSettings.builder() - .x509CertificateSubjectDN("CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US") - .build(); - assertThat(clientSettings.getX509CertificateSubjectDN()).isEqualTo("CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US"); + .x509CertificateSubjectDN("CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US") + .build(); + assertThat(clientSettings.getX509CertificateSubjectDN()) + .isEqualTo("CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US"); } @Test diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/TokenSettingsTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/TokenSettingsTests.java index 3c6da6c7..e0d6a527 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/TokenSettingsTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/settings/TokenSettingsTests.java @@ -153,18 +153,16 @@ public class TokenSettingsTests { @Test public void x509CertificateBoundAccessTokensWhenTrueThenSet() { - TokenSettings tokenSettings = TokenSettings.builder() - .x509CertificateBoundAccessTokens(true) - .build(); + TokenSettings tokenSettings = TokenSettings.builder().x509CertificateBoundAccessTokens(true).build(); assertThat(tokenSettings.isX509CertificateBoundAccessTokens()).isTrue(); } @Test public void settingWhenCustomThenSet() { TokenSettings tokenSettings = TokenSettings.builder() - .setting("name1", "value1") - .settings(settings -> settings.put("name2", "value2")) - .build(); + .setting("name1", "value1") + .settings(settings -> settings.put("name2", "value2")) + .build(); assertThat(tokenSettings.getSettings()).hasSize(10); assertThat(tokenSettings.getSetting("name1")).isEqualTo("value1"); assertThat(tokenSettings.getSetting("name2")).isEqualTo("value2"); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/util/TestX509Certificates.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/util/TestX509Certificates.java index f3d14f42..718431e8 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/util/TestX509Certificates.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/util/TestX509Certificates.java @@ -29,22 +29,25 @@ public final class TestX509Certificates { // Generate the Root certificate (Trust Anchor or most-trusted CA) KeyPair rootKeyPair = X509CertificateUtils.generateRSAKeyPair(); String distinguishedName = "CN=spring-samples-trusted-ca, OU=Spring Samples, O=Spring, C=US"; - X509Certificate rootCertificate = X509CertificateUtils.createTrustAnchorCertificate(rootKeyPair, distinguishedName); + X509Certificate rootCertificate = X509CertificateUtils.createTrustAnchorCertificate(rootKeyPair, + distinguishedName); // Generate the CA (intermediary) certificate KeyPair caKeyPair = X509CertificateUtils.generateRSAKeyPair(); distinguishedName = "CN=spring-samples-ca, OU=Spring Samples, O=Spring, C=US"; - X509Certificate caCertificate = X509CertificateUtils.createCACertificate( - rootCertificate, rootKeyPair.getPrivate(), caKeyPair.getPublic(), distinguishedName); + X509Certificate caCertificate = X509CertificateUtils.createCACertificate(rootCertificate, + rootKeyPair.getPrivate(), caKeyPair.getPublic(), distinguishedName); // Generate certificate for demo-client-sample KeyPair demoClientKeyPair = X509CertificateUtils.generateRSAKeyPair(); distinguishedName = "CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US"; - X509Certificate demoClientCertificate = X509CertificateUtils.createEndEntityCertificate( - caCertificate, caKeyPair.getPrivate(), demoClientKeyPair.getPublic(), distinguishedName); + X509Certificate demoClientCertificate = X509CertificateUtils.createEndEntityCertificate(caCertificate, + caKeyPair.getPrivate(), demoClientKeyPair.getPublic(), distinguishedName); - DEMO_CLIENT_PKI_CERTIFICATE = new X509Certificate[] { demoClientCertificate, caCertificate, rootCertificate }; - } catch (Exception ex) { + DEMO_CLIENT_PKI_CERTIFICATE = new X509Certificate[] { demoClientCertificate, caCertificate, + rootCertificate }; + } + catch (Exception ex) { throw new IllegalStateException(ex); } } @@ -55,10 +58,12 @@ public final class TestX509Certificates { // Generate self-signed certificate for demo-client-sample KeyPair keyPair = X509CertificateUtils.generateRSAKeyPair(); String distinguishedName = "CN=demo-client-sample, OU=Spring Samples, O=Spring, C=US"; - X509Certificate demoClientSelfSignedCertificate = X509CertificateUtils.createTrustAnchorCertificate(keyPair, distinguishedName); + X509Certificate demoClientSelfSignedCertificate = X509CertificateUtils.createTrustAnchorCertificate(keyPair, + distinguishedName); DEMO_CLIENT_SELF_SIGNED_CERTIFICATE = new X509Certificate[] { demoClientSelfSignedCertificate }; - } catch (Exception ex) { + } + catch (Exception ex) { throw new IllegalStateException(ex); } } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/util/X509CertificateUtils.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/util/X509CertificateUtils.java index 56ecca8a..878c78a5 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/util/X509CertificateUtils.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/util/X509CertificateUtils.java @@ -44,15 +44,20 @@ import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; * @author Joe Grandja */ public final class X509CertificateUtils { + private static final String BC_PROVIDER = "BC"; + private static final String SHA256_RSA_SIGNATURE_ALGORITHM = "SHA256withRSA"; + private static final Date DEFAULT_START_DATE; + private static final Date DEFAULT_END_DATE; static { Security.addProvider(new BouncyCastleProvider()); - // Setup default certificate start date to yesterday and end date for 1 year validity + // Setup default certificate start date to yesterday and end date for 1 year + // validity Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DATE, -1); DEFAULT_START_DATE = calendar.getTime(); @@ -69,34 +74,31 @@ public final class X509CertificateUtils { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", BC_PROVIDER); keyPairGenerator.initialize(new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4)); keyPair = keyPairGenerator.generateKeyPair(); - } catch (Exception ex) { + } + catch (Exception ex) { throw new IllegalStateException(ex); } return keyPair; } - public static X509Certificate createTrustAnchorCertificate(KeyPair keyPair, String distinguishedName) throws Exception { + public static X509Certificate createTrustAnchorCertificate(KeyPair keyPair, String distinguishedName) + throws Exception { X500Principal subject = new X500Principal(distinguishedName); BigInteger serialNum = new BigInteger(Long.toString(new SecureRandom().nextLong())); - X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( - subject, - serialNum, - DEFAULT_START_DATE, - DEFAULT_END_DATE, - subject, - keyPair.getPublic()); + X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(subject, serialNum, DEFAULT_START_DATE, + DEFAULT_END_DATE, subject, keyPair.getPublic()); // Add Extensions JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils(); certBuilder - // A BasicConstraints to mark root certificate as CA certificate - .addExtension(Extension.basicConstraints, true, new BasicConstraints(true)) - .addExtension(Extension.subjectKeyIdentifier, false, - extensionUtils.createSubjectKeyIdentifier(keyPair.getPublic())); + // A BasicConstraints to mark root certificate as CA certificate + .addExtension(Extension.basicConstraints, true, new BasicConstraints(true)) + .addExtension(Extension.subjectKeyIdentifier, false, + extensionUtils.createSubjectKeyIdentifier(keyPair.getPublic())); - ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM) - .setProvider(BC_PROVIDER).build(keyPair.getPrivate()); + ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM).setProvider(BC_PROVIDER) + .build(keyPair.getPrivate()); JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BC_PROVIDER); @@ -109,32 +111,26 @@ public final class X509CertificateUtils { X500Principal subject = new X500Principal(distinguishedName); BigInteger serialNum = new BigInteger(Long.toString(new SecureRandom().nextLong())); - X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( - signerCert.getSubjectX500Principal(), - serialNum, - DEFAULT_START_DATE, - DEFAULT_END_DATE, - subject, - certKey); + X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(signerCert.getSubjectX500Principal(), + serialNum, DEFAULT_START_DATE, DEFAULT_END_DATE, subject, certKey); // Add Extensions JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils(); certBuilder - // A BasicConstraints to mark as CA certificate and how many CA certificates can follow it in the chain - // (with 0 meaning the chain ends with the next certificate in the chain). - .addExtension(Extension.basicConstraints, true, new BasicConstraints(0)) - // KeyUsage specifies what the public key in the certificate can be used for. - // In this case, it can be used for signing other certificates and/or - // signing Certificate Revocation Lists (CRLs). - .addExtension(Extension.keyUsage, true, - new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign)) - .addExtension(Extension.authorityKeyIdentifier, false, - extensionUtils.createAuthorityKeyIdentifier(signerCert)) - .addExtension(Extension.subjectKeyIdentifier, false, - extensionUtils.createSubjectKeyIdentifier(certKey)); + // A BasicConstraints to mark as CA certificate and how many CA certificates + // can follow it in the chain + // (with 0 meaning the chain ends with the next certificate in the chain). + .addExtension(Extension.basicConstraints, true, new BasicConstraints(0)) + // KeyUsage specifies what the public key in the certificate can be used for. + // In this case, it can be used for signing other certificates and/or + // signing Certificate Revocation Lists (CRLs). + .addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign)) + .addExtension(Extension.authorityKeyIdentifier, false, + extensionUtils.createAuthorityKeyIdentifier(signerCert)) + .addExtension(Extension.subjectKeyIdentifier, false, extensionUtils.createSubjectKeyIdentifier(certKey)); - ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM) - .setProvider(BC_PROVIDER).build(signerKey); + ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM).setProvider(BC_PROVIDER) + .build(signerKey); JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BC_PROVIDER); @@ -147,26 +143,18 @@ public final class X509CertificateUtils { X500Principal subject = new X500Principal(distinguishedName); BigInteger serialNum = new BigInteger(Long.toString(new SecureRandom().nextLong())); - X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( - signerCert.getSubjectX500Principal(), - serialNum, - DEFAULT_START_DATE, - DEFAULT_END_DATE, - subject, - certKey); + X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(signerCert.getSubjectX500Principal(), + serialNum, DEFAULT_START_DATE, DEFAULT_END_DATE, subject, certKey); JcaX509ExtensionUtils extensionUtils = new JcaX509ExtensionUtils(); - certBuilder - .addExtension(Extension.basicConstraints, true, new BasicConstraints(false)) - .addExtension(Extension.keyUsage, true, - new KeyUsage(KeyUsage.digitalSignature)) - .addExtension(Extension.authorityKeyIdentifier, false, - extensionUtils.createAuthorityKeyIdentifier(signerCert)) - .addExtension(Extension.subjectKeyIdentifier, false, - extensionUtils.createSubjectKeyIdentifier(certKey)); + certBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(false)) + .addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature)) + .addExtension(Extension.authorityKeyIdentifier, false, + extensionUtils.createAuthorityKeyIdentifier(signerCert)) + .addExtension(Extension.subjectKeyIdentifier, false, extensionUtils.createSubjectKeyIdentifier(certKey)); - ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM) - .setProvider(BC_PROVIDER).build(signerKey); + ContentSigner signer = new JcaContentSignerBuilder(SHA256_RSA_SIGNATURE_ALGORITHM).setProvider(BC_PROVIDER) + .build(signerKey); JcaX509CertificateConverter converter = new JcaX509CertificateConverter().setProvider(BC_PROVIDER); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java index efd2a664..862bab62 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java @@ -63,8 +63,8 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests { @Test public void doFilterWhenNotAuthorizationServerMetadataRequestThenNotProcessed() throws Exception { - AuthorizationServerContextHolder.setContext( - new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null)); + AuthorizationServerContextHolder + .setContext(new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null)); String requestUri = "/path"; MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri); @@ -79,8 +79,8 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests { @Test public void doFilterWhenAuthorizationServerMetadataRequestPostThenNotProcessed() throws Exception { - AuthorizationServerContextHolder.setContext( - new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null)); + AuthorizationServerContextHolder + .setContext(new TestAuthorizationServerContext(AuthorizationServerSettings.builder().build(), null)); String requestUri = DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI; MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri); @@ -126,16 +126,24 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests { assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON_VALUE); String authorizationServerMetadataResponse = response.getContentAsString(); assertThat(authorizationServerMetadataResponse).contains("\"issuer\":\"https://example.com\""); - assertThat(authorizationServerMetadataResponse).contains("\"authorization_endpoint\":\"https://example.com/oauth2/v1/authorize\""); - assertThat(authorizationServerMetadataResponse).contains("\"token_endpoint\":\"https://example.com/oauth2/v1/token\""); - assertThat(authorizationServerMetadataResponse).contains("\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); + assertThat(authorizationServerMetadataResponse) + .contains("\"authorization_endpoint\":\"https://example.com/oauth2/v1/authorize\""); + assertThat(authorizationServerMetadataResponse) + .contains("\"token_endpoint\":\"https://example.com/oauth2/v1/token\""); + assertThat(authorizationServerMetadataResponse).contains( + "\"token_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); assertThat(authorizationServerMetadataResponse).contains("\"jwks_uri\":\"https://example.com/oauth2/v1/jwks\""); assertThat(authorizationServerMetadataResponse).contains("\"response_types_supported\":[\"code\"]"); - assertThat(authorizationServerMetadataResponse).contains("\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\",\"urn:ietf:params:oauth:grant-type:token-exchange\"]"); - assertThat(authorizationServerMetadataResponse).contains("\"revocation_endpoint\":\"https://example.com/oauth2/v1/revoke\""); - assertThat(authorizationServerMetadataResponse).contains("\"revocation_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); - assertThat(authorizationServerMetadataResponse).contains("\"introspection_endpoint\":\"https://example.com/oauth2/v1/introspect\""); - assertThat(authorizationServerMetadataResponse).contains("\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); + assertThat(authorizationServerMetadataResponse).contains( + "\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\",\"urn:ietf:params:oauth:grant-type:token-exchange\"]"); + assertThat(authorizationServerMetadataResponse) + .contains("\"revocation_endpoint\":\"https://example.com/oauth2/v1/revoke\""); + assertThat(authorizationServerMetadataResponse).contains( + "\"revocation_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); + assertThat(authorizationServerMetadataResponse) + .contains("\"introspection_endpoint\":\"https://example.com/oauth2/v1/introspect\""); + assertThat(authorizationServerMetadataResponse).contains( + "\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); assertThat(authorizationServerMetadataResponse).contains("\"code_challenge_methods_supported\":[\"S256\"]"); assertThat(authorizationServerMetadataResponse).contains("\"tls_client_certificate_bound_access_tokens\":true"); } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilterTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilterTests.java index 6f2ecefb..47901b63 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilterTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2TokenEndpointFilterTests.java @@ -452,17 +452,16 @@ public class OAuth2TokenEndpointFilterTests { @Test public void doFilterWhenTokenExchangeRequestThenAccessTokenResponse() throws Exception { RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE).build(); - Authentication clientPrincipal = new OAuth2ClientAuthenticationToken( - registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); - OAuth2AccessToken accessToken = new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "token", + .authorizationGrantType(AuthorizationGrantType.TOKEN_EXCHANGE) + .build(); + Authentication clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient, + ClientAuthenticationMethod.CLIENT_SECRET_BASIC, registeredClient.getClientSecret()); + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "token", Instant.now(), Instant.now().plus(Duration.ofHours(1)), new HashSet<>(Arrays.asList("scope1", "scope2"))); OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", Instant.now()); - OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = - new OAuth2AccessTokenAuthenticationToken( - registeredClient, clientPrincipal, accessToken, refreshToken); + OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = new OAuth2AccessTokenAuthenticationToken( + registeredClient, clientPrincipal, accessToken, refreshToken); when(this.authenticationManager.authenticate(any())).thenReturn(accessTokenAuthentication); @@ -478,24 +477,22 @@ public class OAuth2TokenEndpointFilterTests { verifyNoInteractions(filterChain); - ArgumentCaptor tokenExchangeAuthenticationCaptor = - ArgumentCaptor.forClass(OAuth2TokenExchangeAuthenticationToken.class); + ArgumentCaptor tokenExchangeAuthenticationCaptor = ArgumentCaptor + .forClass(OAuth2TokenExchangeAuthenticationToken.class); verify(this.authenticationManager).authenticate(tokenExchangeAuthenticationCaptor.capture()); - OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthenticationToken = - tokenExchangeAuthenticationCaptor.getValue(); + OAuth2TokenExchangeAuthenticationToken tokenExchangeAuthenticationToken = tokenExchangeAuthenticationCaptor + .getValue(); assertThat(tokenExchangeAuthenticationToken.getSubjectToken()).isEqualTo("subject-token"); assertThat(tokenExchangeAuthenticationToken.getSubjectTokenType()).isEqualTo(ACCESS_TOKEN_TYPE); assertThat(tokenExchangeAuthenticationToken.getPrincipal()).isEqualTo(clientPrincipal); assertThat(tokenExchangeAuthenticationToken.getScopes()).isEqualTo(registeredClient.getScopes()); - assertThat(tokenExchangeAuthenticationToken.getAdditionalParameters()) - .containsExactly(entry("custom-param-1", "custom-value-1"), - entry("custom-param-2", new String[] { "custom-value-1", "custom-value-2" })); - assertThat(tokenExchangeAuthenticationToken.getDetails()) - .asInstanceOf(type(WebAuthenticationDetails.class)) - .extracting(WebAuthenticationDetails::getRemoteAddress) - .isEqualTo(REMOTE_ADDRESS); - + assertThat(tokenExchangeAuthenticationToken.getAdditionalParameters()).containsExactly( + entry("custom-param-1", "custom-value-1"), + entry("custom-param-2", new String[] { "custom-value-1", "custom-value-2" })); + assertThat(tokenExchangeAuthenticationToken.getDetails()).asInstanceOf(type(WebAuthenticationDetails.class)) + .extracting(WebAuthenticationDetails::getRemoteAddress) + .isEqualTo(REMOTE_ADDRESS); assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response); @@ -503,10 +500,10 @@ public class OAuth2TokenEndpointFilterTests { OAuth2AccessToken accessTokenResult = accessTokenResponse.getAccessToken(); assertThat(accessTokenResult.getTokenType()).isEqualTo(accessToken.getTokenType()); assertThat(accessTokenResult.getTokenValue()).isEqualTo(accessToken.getTokenValue()); - assertThat(accessTokenResult.getIssuedAt()).isBetween( - accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1)); - assertThat(accessTokenResult.getExpiresAt()).isBetween( - accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1)); + assertThat(accessTokenResult.getIssuedAt()).isBetween(accessToken.getIssuedAt().minusSeconds(1), + accessToken.getIssuedAt().plusSeconds(1)); + assertThat(accessTokenResult.getExpiresAt()).isBetween(accessToken.getExpiresAt().minusSeconds(1), + accessToken.getExpiresAt().plusSeconds(1)); assertThat(accessTokenResult.getScopes()).isEqualTo(accessToken.getScopes()); OAuth2RefreshToken refreshTokenResult = accessTokenResponse.getRefreshToken(); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests.java index fd700c81..b144ee89 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests.java @@ -53,13 +53,16 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; * @author Dmitriy Dubson */ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests { + private final RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); - private final HttpMessageConverter accessTokenHttpResponseConverter = - new OAuth2AccessTokenResponseHttpMessageConverter(); + + private final HttpMessageConverter accessTokenHttpResponseConverter = new OAuth2AccessTokenResponseHttpMessageConverter(); + private final OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken( - this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret()); - private final OAuth2AccessTokenResponseAuthenticationSuccessHandler authenticationSuccessHandler = - new OAuth2AccessTokenResponseAuthenticationSuccessHandler(); + this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, + this.registeredClient.getClientSecret()); + + private final OAuth2AccessTokenResponseAuthenticationSuccessHandler authenticationSuccessHandler = new OAuth2AccessTokenResponseAuthenticationSuccessHandler(); @Test public void setAccessTokenResponseCustomizerWhenNullThenThrowIllegalArgumentException() { @@ -79,23 +82,22 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests { OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken(); Map additionalParameters = Collections.singletonMap("param1", "value1"); - Authentication authentication = new OAuth2AccessTokenAuthenticationToken( - this.registeredClient, this.clientPrincipal, accessToken, refreshToken, additionalParameters); + Authentication authentication = new OAuth2AccessTokenAuthenticationToken(this.registeredClient, + this.clientPrincipal, accessToken, refreshToken, additionalParameters); this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, authentication); OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response); assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo(accessToken.getTokenValue()); assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(accessToken.getTokenType()); - assertThat(accessTokenResponse.getAccessToken().getIssuedAt()).isBetween( - accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1)); - assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween( - accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1)); + assertThat(accessTokenResponse.getAccessToken().getIssuedAt()) + .isBetween(accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1)); + assertThat(accessTokenResponse.getAccessToken().getExpiresAt()) + .isBetween(accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1)); assertThat(accessTokenResponse.getRefreshToken()).isNotNull(); assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo(refreshToken.getTokenValue()); - assertThat(accessTokenResponse.getAdditionalParameters()).containsExactlyInAnyOrderEntriesOf( - Map.of("param1", "value1") - ); + assertThat(accessTokenResponse.getAdditionalParameters()) + .containsExactlyInAnyOrderEntriesOf(Map.of("param1", "value1")); } @Test @@ -103,16 +105,17 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); - assertThatThrownBy(() -> - this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, new TestingAuthenticationToken(this.clientPrincipal, null))) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .extracting("errorCode") - .isEqualTo(OAuth2ErrorCodes.SERVER_ERROR); + assertThatThrownBy(() -> this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, + new TestingAuthenticationToken(this.clientPrincipal, null))) + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .extracting("errorCode") + .isEqualTo(OAuth2ErrorCodes.SERVER_ERROR); } @Test - public void onAuthenticationSuccessWhenAccessTokenResponseCustomizerSetThenAccessTokenResponseCustomized() throws Exception { + public void onAuthenticationSuccessWhenAccessTokenResponseCustomizerSetThenAccessTokenResponseCustomized() + throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); @@ -120,8 +123,8 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests { OAuth2AccessToken accessToken = authorization.getAccessToken().getToken(); OAuth2RefreshToken refreshToken = authorization.getRefreshToken().getToken(); Map additionalParameters = Collections.singletonMap("param1", "value1"); - Authentication authentication = new OAuth2AccessTokenAuthenticationToken( - this.registeredClient, this.clientPrincipal, accessToken, refreshToken, additionalParameters); + Authentication authentication = new OAuth2AccessTokenAuthenticationToken(this.registeredClient, + this.clientPrincipal, accessToken, refreshToken, additionalParameters); Consumer accessTokenResponseCustomizer = (authenticationContext) -> { OAuth2AccessTokenAuthenticationToken accessTokenAuthentication = authenticationContext.getAuthentication(); @@ -136,20 +139,19 @@ public class OAuth2AccessTokenResponseAuthenticationSuccessHandlerTests { OAuth2AccessTokenResponse accessTokenResponse = readAccessTokenResponse(response); assertThat(accessTokenResponse.getAccessToken().getTokenValue()).isEqualTo(accessToken.getTokenValue()); assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(accessToken.getTokenType()); - assertThat(accessTokenResponse.getAccessToken().getIssuedAt()).isBetween( - accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1)); - assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween( - accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1)); + assertThat(accessTokenResponse.getAccessToken().getIssuedAt()) + .isBetween(accessToken.getIssuedAt().minusSeconds(1), accessToken.getIssuedAt().plusSeconds(1)); + assertThat(accessTokenResponse.getAccessToken().getExpiresAt()) + .isBetween(accessToken.getExpiresAt().minusSeconds(1), accessToken.getExpiresAt().plusSeconds(1)); assertThat(accessTokenResponse.getRefreshToken()).isNotNull(); assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo(refreshToken.getTokenValue()); - assertThat(accessTokenResponse.getAdditionalParameters()).containsExactlyInAnyOrderEntriesOf( - Map.of("param1", "value1", "authorization_id", "id") - ); + assertThat(accessTokenResponse.getAdditionalParameters()) + .containsExactlyInAnyOrderEntriesOf(Map.of("param1", "value1", "authorization_id", "id")); } private OAuth2AccessTokenResponse readAccessTokenResponse(MockHttpServletResponse response) throws Exception { - MockClientHttpResponse httpResponse = new MockClientHttpResponse( - response.getContentAsByteArray(), HttpStatus.valueOf(response.getStatus())); + MockClientHttpResponse httpResponse = new MockClientHttpResponse(response.getContentAsByteArray(), + HttpStatus.valueOf(response.getStatus())); return this.accessTokenHttpResponseConverter.read(OAuth2AccessTokenResponse.class, httpResponse); } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverterTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverterTests.java index ba7360ac..05e211bb 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverterTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverterTests.java @@ -41,11 +41,17 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; * @author Steve Riesenberg */ public class OAuth2TokenExchangeAuthenticationConverterTests { + private static final String CLIENT_ID = "client-1"; + private static final String TOKEN_URI = "/oauth2/token"; + private static final String SUBJECT_TOKEN = "EfYu_0jEL"; + private static final String ACTOR_TOKEN = "JlNE_xR1f"; + private static final String ACCESS_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:access_token"; + private static final String JWT_TOKEN_TYPE_VALUE = "urn:ietf:params:oauth:token-type:jwt"; private OAuth2TokenExchangeAuthenticationConverter converter; @@ -222,7 +228,6 @@ public class OAuth2TokenExchangeAuthenticationConverterTests { // @formatter:on } - @Test public void convertWhenMultipleActorTokenParametersThenInvalidRequestError() { MockHttpServletRequest request = createRequest(); @@ -312,8 +317,8 @@ public class OAuth2TokenExchangeAuthenticationConverterTests { securityContext.setAuthentication(new TestingAuthenticationToken(CLIENT_ID, null)); SecurityContextHolder.setContext(securityContext); - OAuth2TokenExchangeAuthenticationToken authentication = - (OAuth2TokenExchangeAuthenticationToken) this.converter.convert(request); + OAuth2TokenExchangeAuthenticationToken authentication = (OAuth2TokenExchangeAuthenticationToken) this.converter + .convert(request); assertThat(authentication).isNotNull(); assertThat(authentication.getResources()).containsExactly("https://mydomain.com/resource1", "https://mydomain.com/resource2"); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/X509ClientCertificateAuthenticationConverterTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/X509ClientCertificateAuthenticationConverterTests.java index 37de0fe0..42e93448 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/X509ClientCertificateAuthenticationConverterTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/X509ClientCertificateAuthenticationConverterTests.java @@ -39,6 +39,7 @@ import static org.assertj.core.api.Assertions.entry; * @author Joe Grandja */ public class X509ClientCertificateAuthenticationConverterTests { + private final X509ClientCertificateAuthenticationConverter converter = new X509ClientCertificateAuthenticationConverter(); @Test @@ -51,8 +52,7 @@ public class X509ClientCertificateAuthenticationConverterTests { @Test public void convertWhenEmptyX509CertificateThenReturnNull() { MockHttpServletRequest request = new MockHttpServletRequest(); - request.setAttribute("jakarta.servlet.request.X509Certificate", - new X509Certificate[0]); + request.setAttribute("jakarta.servlet.request.X509Certificate", new X509Certificate[0]); Authentication authentication = this.converter.convert(request); assertThat(authentication).isNull(); } @@ -62,11 +62,10 @@ public class X509ClientCertificateAuthenticationConverterTests { MockHttpServletRequest request = new MockHttpServletRequest(); request.setAttribute("jakarta.servlet.request.X509Certificate", TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE); - assertThatThrownBy(() -> this.converter.convert(request)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .extracting("errorCode") - .isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST); + assertThatThrownBy(() -> this.converter.convert(request)).isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .extracting("errorCode") + .isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST); } @Test @@ -76,11 +75,10 @@ public class X509ClientCertificateAuthenticationConverterTests { TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE); request.addParameter(OAuth2ParameterNames.CLIENT_ID, "client-1"); request.addParameter(OAuth2ParameterNames.CLIENT_ID, "client-2"); - assertThatThrownBy(() -> this.converter.convert(request)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .extracting("errorCode") - .isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST); + assertThatThrownBy(() -> this.converter.convert(request)).isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .extracting("errorCode") + .isEqualTo(OAuth2ErrorCodes.INVALID_REQUEST); } @Test @@ -93,16 +91,16 @@ public class X509ClientCertificateAuthenticationConverterTests { request.addParameter(OAuth2ParameterNames.CODE, "code"); request.addParameter("custom-param-1", "custom-value-1"); request.addParameter("custom-param-2", "custom-value-1", "custom-value-2"); - OAuth2ClientAuthenticationToken authentication = (OAuth2ClientAuthenticationToken) this.converter.convert(request); + OAuth2ClientAuthenticationToken authentication = (OAuth2ClientAuthenticationToken) this.converter + .convert(request); assertThat(authentication.getPrincipal()).isEqualTo("client-1"); assertThat(authentication.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_PKI_CERTIFICATE); - assertThat(authentication.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH); - assertThat(authentication.getAdditionalParameters()) - .containsOnly( - entry(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()), - entry(OAuth2ParameterNames.CODE, "code"), - entry("custom-param-1", "custom-value-1"), - entry("custom-param-2", new String[] {"custom-value-1", "custom-value-2"})); + assertThat(authentication.getClientAuthenticationMethod()) + .isEqualTo(ClientAuthenticationMethod.TLS_CLIENT_AUTH); + assertThat(authentication.getAdditionalParameters()).containsOnly( + entry(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()), + entry(OAuth2ParameterNames.CODE, "code"), entry("custom-param-1", "custom-value-1"), + entry("custom-param-2", new String[] { "custom-value-1", "custom-value-2" })); } @Test @@ -115,16 +113,16 @@ public class X509ClientCertificateAuthenticationConverterTests { request.addParameter(OAuth2ParameterNames.CODE, "code"); request.addParameter("custom-param-1", "custom-value-1"); request.addParameter("custom-param-2", "custom-value-1", "custom-value-2"); - OAuth2ClientAuthenticationToken authentication = (OAuth2ClientAuthenticationToken) this.converter.convert(request); + OAuth2ClientAuthenticationToken authentication = (OAuth2ClientAuthenticationToken) this.converter + .convert(request); assertThat(authentication.getPrincipal()).isEqualTo("client-1"); assertThat(authentication.getCredentials()).isEqualTo(TestX509Certificates.DEMO_CLIENT_SELF_SIGNED_CERTIFICATE); - assertThat(authentication.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH); - assertThat(authentication.getAdditionalParameters()) - .containsOnly( - entry(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()), - entry(OAuth2ParameterNames.CODE, "code"), - entry("custom-param-1", "custom-value-1"), - entry("custom-param-2", new String[] {"custom-value-1", "custom-value-2"})); + assertThat(authentication.getClientAuthenticationMethod()) + .isEqualTo(ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH); + assertThat(authentication.getAdditionalParameters()).containsOnly( + entry(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.AUTHORIZATION_CODE.getValue()), + entry(OAuth2ParameterNames.CODE, "code"), entry("custom-param-1", "custom-value-1"), + entry("custom-param-2", new String[] { "custom-value-1", "custom-value-2" })); } }