diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationConsentService.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationConsentService.java index cdbf9ad1..b7bffe68 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationConsentService.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationConsentService.java @@ -75,8 +75,9 @@ public class JdbcOAuth2AuthorizationConsentService implements OAuth2Authorizatio @Override public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - hints.resources().registerResource(new ClassPathResource( - "org/springframework/security/oauth2/server/authorization/oauth2-authorization-consent-schema.sql")); + hints.resources() + .registerResource(new ClassPathResource( + "org/springframework/security/oauth2/server/authorization/oauth2-authorization-consent-schema.sql")); } } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java index 0dce3f3c..526152e5 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JdbcOAuth2AuthorizationService.java @@ -101,8 +101,9 @@ public class JdbcOAuth2AuthorizationService implements OAuth2AuthorizationServic @Override public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - hints.resources().registerResource(new ClassPathResource( - "org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql")); + hints.resources() + .registerResource(new ClassPathResource( + "org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql")); } } 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 6d196844..f5739ba9 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 @@ -51,19 +51,22 @@ import org.springframework.security.web.savedrequest.DefaultSavedRequest; import org.springframework.util.ClassUtils; /** - * {@link BeanRegistrationAotProcessor} that detects specific registered beans and contributes the required {@link RuntimeHints}. - * Statically registered via META-INF/spring/aot.factories. + * {@link BeanRegistrationAotProcessor} that detects specific registered beans and + * contributes the required {@link RuntimeHints}. Statically registered via + * META-INF/spring/aot.factories. * * @author Joe Grandja * @author Josh Long * @since 1.2 */ class OAuth2AuthorizationServerBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor { + private boolean jackson2Contributed; @Override public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { String beanClassName = registeredBean.getBeanClass().getName(); + // @formatter:off if ((beanClassName.equals("org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService") || beanClassName.equals("org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository")) && !jackson2Contributed) { @@ -72,10 +75,13 @@ class OAuth2AuthorizationServerBeanRegistrationAotProcessor implements BeanRegis jackson2Contributed = true; return jackson2Contribution; } + // @formatter:on return null; } - private static class Jackson2ConfigurationBeanRegistrationAotContribution implements BeanRegistrationAotContribution { + private static class Jackson2ConfigurationBeanRegistrationAotContribution + implements BeanRegistrationAotContribution { + private final BindingReflectionHintsRegistrar reflectionHintsRegistrar = new BindingReflectionHintsRegistrar(); @Override @@ -84,50 +90,40 @@ class OAuth2AuthorizationServerBeanRegistrationAotProcessor implements BeanRegis } private void registerHints(RuntimeHints hints) { - // Collections -> UnmodifiableSet, UnmodifiableList, UnmodifiableMap, UnmodifiableRandomAccessList, etc. - hints.reflection().registerType(Collections.class, - MemberCategory.DECLARED_CLASSES); + // Collections -> UnmodifiableSet, UnmodifiableList, UnmodifiableMap, + // UnmodifiableRandomAccessList, etc. + hints.reflection().registerType(Collections.class, MemberCategory.DECLARED_CLASSES); // HashSet - hints.reflection().registerType(HashSet.class, - MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, - MemberCategory.INVOKE_DECLARED_METHODS); + hints.reflection() + .registerType(HashSet.class, MemberCategory.DECLARED_FIELDS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS); // Spring Security and Spring Authorization Server - hints.reflection().registerTypes( - Arrays.asList( - TypeReference.of(AbstractAuthenticationToken.class), - TypeReference.of(DefaultSavedRequest.Builder.class), - TypeReference.of(WebAuthenticationDetails.class), - TypeReference.of(UsernamePasswordAuthenticationToken.class), - TypeReference.of(User.class), - TypeReference.of(DefaultOidcUser.class), - TypeReference.of(DefaultOAuth2User.class), - TypeReference.of(OidcUserAuthority.class), - TypeReference.of(OAuth2UserAuthority.class), - TypeReference.of(SimpleGrantedAuthority.class), - TypeReference.of(OidcIdToken.class), - TypeReference.of(AbstractOAuth2Token.class), - TypeReference.of(OidcUserInfo.class), - TypeReference.of(OAuth2AuthorizationRequest.class), - TypeReference.of(AuthorizationGrantType.class), - TypeReference.of(OAuth2AuthorizationResponseType.class), - TypeReference.of(OAuth2TokenFormat.class) - ), builder -> - builder.withMembers(MemberCategory.DECLARED_FIELDS, - MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS) - ); + hints.reflection() + .registerTypes(Arrays.asList(TypeReference.of(AbstractAuthenticationToken.class), + TypeReference.of(DefaultSavedRequest.Builder.class), + TypeReference.of(WebAuthenticationDetails.class), + TypeReference.of(UsernamePasswordAuthenticationToken.class), TypeReference.of(User.class), + TypeReference.of(DefaultOidcUser.class), TypeReference.of(DefaultOAuth2User.class), + TypeReference.of(OidcUserAuthority.class), TypeReference.of(OAuth2UserAuthority.class), + TypeReference.of(SimpleGrantedAuthority.class), TypeReference.of(OidcIdToken.class), + TypeReference.of(AbstractOAuth2Token.class), TypeReference.of(OidcUserInfo.class), + TypeReference.of(OAuth2AuthorizationRequest.class), + TypeReference.of(AuthorizationGrantType.class), + TypeReference.of(OAuth2AuthorizationResponseType.class), + TypeReference.of(OAuth2TokenFormat.class)), + builder -> builder.withMembers(MemberCategory.DECLARED_FIELDS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS)); // Jackson Modules - Spring Security and Spring Authorization Server - hints.reflection().registerTypes( - Arrays.asList( - TypeReference.of(CoreJackson2Module.class), - TypeReference.of(WebServletJackson2Module.class), - TypeReference.of(OAuth2AuthorizationServerJackson2Module.class) - ), builder -> - builder.withMembers(MemberCategory.DECLARED_FIELDS, - MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS) - ); + hints.reflection() + .registerTypes( + Arrays.asList(TypeReference.of(CoreJackson2Module.class), + TypeReference.of(WebServletJackson2Module.class), + TypeReference.of(OAuth2AuthorizationServerJackson2Module.class)), + builder -> builder.withMembers(MemberCategory.DECLARED_FIELDS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS)); // Jackson Mixins - Spring Security and Spring Authorization Server this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), @@ -136,8 +132,8 @@ class OAuth2AuthorizationServerBeanRegistrationAotProcessor implements BeanRegis loadClass("org.springframework.security.jackson2.UnmodifiableListMixin")); this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass("org.springframework.security.jackson2.UnmodifiableMapMixin")); - this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), - loadClass("org.springframework.security.oauth2.server.authorization.jackson2.UnmodifiableMapMixin")); + this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass( + "org.springframework.security.oauth2.server.authorization.jackson2.UnmodifiableMapMixin")); this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass("org.springframework.security.oauth2.server.authorization.jackson2.HashSetMixin")); this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), @@ -150,28 +146,29 @@ 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.OAuth2AuthorizationRequestMixin")); - 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.OAuth2AuthorizationRequestMixin")); + 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", ClassUtils.getDefaultClassLoader())) { // Jackson Module (and required types) - Spring Security OAuth2 Client - hints.reflection().registerTypes( - Arrays.asList( - TypeReference.of("org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module"), - TypeReference.of("org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken") - ), builder -> - builder.withMembers(MemberCategory.DECLARED_FIELDS, - MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS) - ); + hints.reflection() + .registerTypes(Arrays.asList( + TypeReference + .of("org.springframework.security.oauth2.client.jackson2.OAuth2ClientJackson2Module"), + TypeReference + .of("org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken")), + builder -> builder.withMembers(MemberCategory.DECLARED_FIELDS, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, + MemberCategory.INVOKE_DECLARED_METHODS)); // Jackson Mixins - Spring Security OAuth2 Client - this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), - loadClass("org.springframework.security.oauth2.client.jackson2.OAuth2AuthenticationTokenMixin")); + this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass( + "org.springframework.security.oauth2.client.jackson2.OAuth2AuthenticationTokenMixin")); this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), loadClass("org.springframework.security.oauth2.client.jackson2.DefaultOidcUserMixin")); this.reflectionHintsRegistrar.registerReflectionHints(hints.reflection(), @@ -190,7 +187,8 @@ class OAuth2AuthorizationServerBeanRegistrationAotProcessor implements BeanRegis private static Class loadClass(String className) { try { return Class.forName(className); - } catch (ClassNotFoundException ex) { + } + catch (ClassNotFoundException ex) { throw new RuntimeException(ex); } } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/ClientSecretAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/ClientSecretAuthenticationProvider.java index 8d985d57..3c60a7a0 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/ClientSecretAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/ClientSecretAuthenticationProvider.java @@ -123,8 +123,9 @@ public final class ClientSecretAuthenticationProvider implements AuthenticationP String clientSecret = clientAuthentication.getCredentials().toString(); if (!this.passwordEncoder.matches(clientSecret, registeredClient.getClientSecret())) { if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.format("Invalid request: client_secret does not match" + - " for registered client '%s'", registeredClient.getId())); + this.logger.debug(LogMessage.format( + "Invalid request: client_secret does not match" + " for registered client '%s'", + registeredClient.getId())); } throwInvalidClient(OAuth2ParameterNames.CLIENT_SECRET); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/CodeVerifierAuthenticator.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/CodeVerifierAuthenticator.java index eceaa302..71a29312 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/CodeVerifierAuthenticator.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/CodeVerifierAuthenticator.java @@ -98,11 +98,11 @@ final class CodeVerifierAuthenticator { .get(PkceParameterNames.CODE_CHALLENGE); String codeVerifier = (String) parameters.get(PkceParameterNames.CODE_VERIFIER); if (!StringUtils.hasText(codeChallenge)) { - if (registeredClient.getClientSettings().isRequireProofKey() || - StringUtils.hasText(codeVerifier)) { + if (registeredClient.getClientSettings().isRequireProofKey() || StringUtils.hasText(codeVerifier)) { if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.format("Invalid request: code_challenge is required" + - " for registered client '%s'", registeredClient.getId())); + this.logger.debug(LogMessage.format( + "Invalid request: code_challenge is required" + " for registered client '%s'", + registeredClient.getId())); } throwInvalidGrant(PkceParameterNames.CODE_CHALLENGE); } @@ -122,8 +122,9 @@ final class CodeVerifierAuthenticator { .get(PkceParameterNames.CODE_CHALLENGE_METHOD); if (!codeVerifierValid(codeVerifier, codeChallenge, codeChallengeMethod)) { if (this.logger.isDebugEnabled()) { - this.logger.debug(LogMessage.format("Invalid request: code_verifier is missing or invalid" + - " for registered client '%s'", registeredClient.getId())); + this.logger.debug(LogMessage.format( + "Invalid request: code_verifier is missing or invalid" + " for registered client '%s'", + registeredClient.getId())); } throwInvalidGrant(PkceParameterNames.CODE_VERIFIER); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationValidator.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationValidator.java index b574ac83..3b8eb1b4 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationValidator.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationValidator.java @@ -56,6 +56,7 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationValidator implements Consumer { private static final String ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1"; + private static final Log LOGGER = LogFactory.getLog(OAuth2AuthorizationCodeRequestAuthenticationValidator.class); /** @@ -87,8 +88,9 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationValidator 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())); } throwError(OAuth2ErrorCodes.INVALID_SCOPE, OAuth2ParameterNames.SCOPE, authorizationCodeRequestAuthentication, registeredClient); @@ -113,8 +115,8 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationValidator } if (requestedRedirect == null || requestedRedirect.getFragment() != null) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(LogMessage.format("Invalid request: redirect_uri is missing or contains a fragment" + - " for registered client '%s'", registeredClient.getId())); + LOGGER.debug(LogMessage.format("Invalid request: redirect_uri is missing or contains a fragment" + + " for registered client '%s'", registeredClient.getId())); } throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.REDIRECT_URI, authorizationCodeRequestAuthentication, registeredClient); @@ -148,8 +150,9 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationValidator } if (!validRedirectUri) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(LogMessage.format("Invalid request: redirect_uri does not match" + - " for registered client '%s'", registeredClient.getId())); + LOGGER.debug(LogMessage.format( + "Invalid request: redirect_uri does not match" + " for registered client '%s'", + registeredClient.getId())); } throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.REDIRECT_URI, authorizationCodeRequestAuthentication, registeredClient); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/client/JdbcRegisteredClientRepository.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/client/JdbcRegisteredClientRepository.java index 9b6d7cf1..b63c6d5e 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/client/JdbcRegisteredClientRepository.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/client/JdbcRegisteredClientRepository.java @@ -86,8 +86,9 @@ public class JdbcRegisteredClientRepository implements RegisteredClientRepositor @Override public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - hints.resources().registerResource(new ClassPathResource( - "org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql")); + hints.resources() + .registerResource(new ClassPathResource( + "org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql")); } } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientConfigurationAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientConfigurationAuthenticationProvider.java index 1311b635..8dfd3734 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientConfigurationAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientConfigurationAuthenticationProvider.java @@ -86,12 +86,14 @@ public final class OidcClientConfigurationAuthenticationProvider implements Auth } /** - * Sets the {@link Converter} used for converting a {@link RegisteredClient} to an {@link OidcClientRegistration}. - * - * @param clientRegistrationConverter the {@link Converter} used for converting a {@link RegisteredClient} to an {@link OidcClientRegistration} + * Sets the {@link Converter} used for converting a {@link RegisteredClient} to an + * {@link OidcClientRegistration}. + * @param clientRegistrationConverter the {@link Converter} used for converting a + * {@link RegisteredClient} to an {@link OidcClientRegistration} * @since 1.2.0 */ - public void setClientRegistrationConverter(Converter clientRegistrationConverter) { + public void setClientRegistrationConverter( + Converter clientRegistrationConverter) { Assert.notNull(clientRegistrationConverter, "clientRegistrationConverter cannot be null"); this.clientRegistrationConverter = clientRegistrationConverter; } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProvider.java index c79290f8..81ab169d 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProvider.java @@ -185,12 +185,14 @@ public final class OidcClientRegistrationAuthenticationProvider implements Authe } /** - * Sets the {@link Converter} used for converting a {@link RegisteredClient} to an {@link OidcClientRegistration}. - * - * @param clientRegistrationConverter the {@link Converter} used for converting a {@link RegisteredClient} to an {@link OidcClientRegistration} + * Sets the {@link Converter} used for converting a {@link RegisteredClient} to an + * {@link OidcClientRegistration}. + * @param clientRegistrationConverter the {@link Converter} used for converting a + * {@link RegisteredClient} to an {@link OidcClientRegistration} * @since 1.2.0 */ - public void setClientRegistrationConverter(Converter clientRegistrationConverter) { + public void setClientRegistrationConverter( + Converter clientRegistrationConverter) { Assert.notNull(clientRegistrationConverter, "clientRegistrationConverter cannot be null"); this.clientRegistrationConverter = clientRegistrationConverter; } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/converter/OidcClientRegistrationRegisteredClientConverter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/converter/OidcClientRegistrationRegisteredClientConverter.java index e64055e7..ffd76019 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/converter/OidcClientRegistrationRegisteredClientConverter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/converter/OidcClientRegistrationRegisteredClientConverter.java @@ -34,15 +34,19 @@ import org.springframework.security.oauth2.server.authorization.settings.TokenSe import org.springframework.util.CollectionUtils; /** - * A {@link Converter} that converts the provided {@link OidcClientRegistration} to a {@link RegisteredClient}. + * A {@link Converter} that converts the provided {@link OidcClientRegistration} to a + * {@link RegisteredClient}. * * @author Joe Grandja * @author Dmitriy Dubson * @since 1.2.0 */ -public final class OidcClientRegistrationRegisteredClientConverter implements Converter { +public final class OidcClientRegistrationRegisteredClientConverter + implements Converter { + private static final StringKeyGenerator CLIENT_ID_GENERATOR = new Base64StringKeyGenerator( Base64.getUrlEncoder().withoutPadding(), 32); + private static final StringKeyGenerator CLIENT_SECRET_GENERATOR = new Base64StringKeyGenerator( Base64.getUrlEncoder().withoutPadding(), 48); @@ -125,4 +129,3 @@ public final class OidcClientRegistrationRegisteredClientConverter implements Co } } - diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/converter/RegisteredClientOidcClientRegistrationConverter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/converter/RegisteredClientOidcClientRegistrationConverter.java index 8a707261..e81d6ee9 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/converter/RegisteredClientOidcClientRegistrationConverter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/converter/RegisteredClientOidcClientRegistrationConverter.java @@ -28,12 +28,14 @@ import org.springframework.util.CollectionUtils; import org.springframework.web.util.UriComponentsBuilder; /** - * A {@link Converter} that converts the provided {@link RegisteredClient} to an {@link OidcClientRegistration}. + * A {@link Converter} that converts the provided {@link RegisteredClient} to an + * {@link OidcClientRegistration}. * * @author Joe Grandja * @since 1.2.0 */ -public final class RegisteredClientOidcClientRegistrationConverter implements Converter { +public final class RegisteredClientOidcClientRegistrationConverter + implements Converter { @Override public OidcClientRegistration convert(RegisteredClient registeredClient) { 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 d4dc1a3c..135e908f 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 @@ -99,27 +99,27 @@ 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()) - .tokenRevocationEndpoint(asUrl(issuer, authorizationServerSettings.getTokenRevocationEndpoint())) - .tokenRevocationEndpointAuthenticationMethods(clientAuthenticationMethods()) - .tokenIntrospectionEndpoint(asUrl(issuer, authorizationServerSettings.getTokenIntrospectionEndpoint())) - .tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods()) - .codeChallengeMethod("S256") - .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()) + .tokenRevocationEndpoint(asUrl(issuer, authorizationServerSettings.getTokenRevocationEndpoint())) + .tokenRevocationEndpointAuthenticationMethods(clientAuthenticationMethods()) + .tokenIntrospectionEndpoint(asUrl(issuer, authorizationServerSettings.getTokenIntrospectionEndpoint())) + .tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods()) + .codeChallengeMethod("S256") + .subjectType("public") + .idTokenSigningAlgorithm(SignatureAlgorithm.RS256.getName()) + .scope(OidcScopes.OPENID); this.providerConfigurationCustomizer.accept(providerConfiguration); diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2RefreshTokenGenerator.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2RefreshTokenGenerator.java index 25f99d34..8c5855aa 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2RefreshTokenGenerator.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/token/OAuth2RefreshTokenGenerator.java @@ -57,10 +57,12 @@ public final class OAuth2RefreshTokenGenerator implements OAuth2TokenGenerator errorResponseConverter = new OAuth2ErrorHttpMessageConverter(); @Override @@ -56,19 +59,21 @@ public final class OAuth2ErrorAuthenticationFailureHandler implements Authentica if (authenticationException instanceof OAuth2AuthenticationException) { OAuth2Error error = ((OAuth2AuthenticationException) authenticationException).getError(); this.errorResponseConverter.write(error, null, httpResponse); - } else { + } + else { if (this.logger.isWarnEnabled()) { - this.logger.warn(AuthenticationException.class.getSimpleName() + " must be of type " + - OAuth2AuthenticationException.class.getName() + - " but was " + authenticationException.getClass().getName()); + this.logger.warn(AuthenticationException.class.getSimpleName() + " must be of type " + + OAuth2AuthenticationException.class.getName() + " but was " + + authenticationException.getClass().getName()); } } } /** - * Sets the {@link HttpMessageConverter} used for converting an {@link OAuth2Error} to an HTTP response. - * - * @param errorResponseConverter the {@link HttpMessageConverter} used for converting an {@link OAuth2Error} to an HTTP response + * Sets the {@link HttpMessageConverter} used for converting an {@link OAuth2Error} to + * an HTTP response. + * @param errorResponseConverter the {@link HttpMessageConverter} used for converting + * an {@link OAuth2Error} to an HTTP response */ public void setErrorResponseConverter(HttpMessageConverter errorResponseConverter) { Assert.notNull(errorResponseConverter, "errorResponseConverter cannot be null"); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java index f8aad7f9..cb1210d4 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProviderTests.java @@ -406,8 +406,8 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests { doAnswer(answer -> { OAuth2TokenContext context = answer.getArgument(0); if (OAuth2TokenType.REFRESH_TOKEN.equals(context.getTokenType())) { - return new OAuth2AccessToken( - OAuth2AccessToken.TokenType.BEARER, "access-token", Instant.now(), Instant.now().plusSeconds(300)); + return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", Instant.now(), + Instant.now().plusSeconds(300)); } else { return answer.callRealMethod(); @@ -415,12 +415,13 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests { }).when(this.tokenGenerator).generate(any()); assertThatThrownBy(() -> this.authenticationProvider.authenticate(authentication)) - .isInstanceOf(OAuth2AuthenticationException.class) - .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) - .satisfies(error -> { - assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.SERVER_ERROR); - assertThat(error.getDescription()).contains("The token generator failed to generate a valid refresh token."); - }); + .isInstanceOf(OAuth2AuthenticationException.class) + .extracting(ex -> ((OAuth2AuthenticationException) ex).getError()) + .satisfies(error -> { + assertThat(error.getErrorCode()).isEqualTo(OAuth2ErrorCodes.SERVER_ERROR); + assertThat(error.getDescription()) + .contains("The token generator failed to generate a valid refresh token."); + }); } @Test 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 8a18cbce..d560c64d 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 @@ -467,46 +467,52 @@ public class OAuth2AuthorizationCodeGrantTests { this.spring.register(AuthorizationServerConfigurationWithCustomRefreshTokenGenerator.class).autowire(); RegisteredClient registeredClient = TestRegisteredClients.registeredPublicClient() - .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) - .build(); + .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) + .build(); this.registeredClientRepository.save(registeredClient); - MvcResult mvcResult = this.mvc.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI) + MvcResult mvcResult = this.mvc + .perform(get(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(); + .andExpect(status().is3xxRedirection()) + .andReturn(); String redirectedUrl = mvcResult.getResponse().getRedirectedUrl(); assertThat(redirectedUrl).matches("https://example.com\\?code=.{15,}&state=" + STATE_URL_ENCODED); String authorizationCode = extractParameterFromRedirectUri(redirectedUrl, "code"); - OAuth2Authorization authorizationCodeAuthorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE); + OAuth2Authorization authorizationCodeAuthorization = this.authorizationService.findByToken(authorizationCode, + AUTHORIZATION_CODE_TOKEN_TYPE); assertThat(authorizationCodeAuthorization).isNotNull(); - assertThat(authorizationCodeAuthorization.getAuthorizationGrantType()).isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); + assertThat(authorizationCodeAuthorization.getAuthorizationGrantType()) + .isEqualTo(AuthorizationGrantType.AUTHORIZATION_CODE); - this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) + this.mvc + .perform(post(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").isNotEmpty()) - .andExpect(jsonPath("$.scope").isNotEmpty()); + .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").isNotEmpty()) + .andExpect(jsonPath("$.scope").isNotEmpty()); OAuth2Authorization authorization = this.authorizationService.findById(authorizationCodeAuthorization.getId()); assertThat(authorization).isNotNull(); assertThat(authorization.getAccessToken()).isNotNull(); assertThat(authorization.getRefreshToken()).isNotNull(); - OAuth2Authorization.Token authorizationCodeToken = authorization.getToken(OAuth2AuthorizationCode.class); + OAuth2Authorization.Token authorizationCodeToken = authorization + .getToken(OAuth2AuthorizationCode.class); assertThat(authorizationCodeToken).isNotNull(); - assertThat(authorizationCodeToken.getMetadata().get(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME)).isEqualTo(true); + assertThat(authorizationCodeToken.getMetadata().get(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME)) + .isEqualTo(true); } @Test @@ -1032,7 +1038,8 @@ public class OAuth2AuthorizationCodeGrantTests { @EnableWebSecurity @Import(OAuth2AuthorizationServerConfiguration.class) - static class AuthorizationServerConfigurationWithCustomRefreshTokenGenerator extends AuthorizationServerConfiguration { + static class AuthorizationServerConfigurationWithCustomRefreshTokenGenerator + extends AuthorizationServerConfiguration { @Bean JwtEncoder jwtEncoder() { @@ -1048,8 +1055,9 @@ public class OAuth2AuthorizationCodeGrantTests { } private static final class CustomRefreshTokenGenerator implements OAuth2TokenGenerator { - private final StringKeyGenerator refreshTokenGenerator = - new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96); + + private final StringKeyGenerator refreshTokenGenerator = new Base64StringKeyGenerator( + Base64.getUrlEncoder().withoutPadding(), 96); @Nullable @Override @@ -1058,7 +1066,8 @@ public class OAuth2AuthorizationCodeGrantTests { return null; } Instant issuedAt = Instant.now(); - Instant expiresAt = issuedAt.plus(context.getRegisteredClient().getTokenSettings().getRefreshTokenTimeToLive()); + Instant expiresAt = issuedAt + .plus(context.getRegisteredClient().getTokenSettings().getRefreshTokenTimeToLive()); return new OAuth2RefreshToken(this.refreshTokenGenerator.generateKey(), issuedAt, expiresAt); } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2RefreshTokenGrantTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2RefreshTokenGrantTests.java index 23ba2a5c..4bd6846a 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2RefreshTokenGrantTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2RefreshTokenGrantTests.java @@ -248,24 +248,24 @@ public class OAuth2RefreshTokenGrantTests { this.spring.register(AuthorizationServerConfigurationWithPublicClientAuthentication.class).autowire(); RegisteredClient registeredClient = TestRegisteredClients.registeredPublicClient() - .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) - .build(); + .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) + .build(); this.registeredClientRepository.save(registeredClient); OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build(); this.authorizationService.save(authorization); - this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) - .params(getRefreshTokenRequestParameters(authorization)) + this.mvc + .perform(post(DEFAULT_TOKEN_ENDPOINT_URI).params(getRefreshTokenRequestParameters(authorization)) .param(OAuth2ParameterNames.CLIENT_ID, registeredClient.getClientId())) - .andExpect(status().isOk()) - .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) - .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) - .andExpect(jsonPath("$.access_token").isNotEmpty()) - .andExpect(jsonPath("$.token_type").isNotEmpty()) - .andExpect(jsonPath("$.expires_in").isNotEmpty()) - .andExpect(jsonPath("$.refresh_token").isNotEmpty()) - .andExpect(jsonPath("$.scope").isNotEmpty()); + .andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) + .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) + .andExpect(jsonPath("$.access_token").isNotEmpty()) + .andExpect(jsonPath("$.token_type").isNotEmpty()) + .andExpect(jsonPath("$.expires_in").isNotEmpty()) + .andExpect(jsonPath("$.refresh_token").isNotEmpty()) + .andExpect(jsonPath("$.scope").isNotEmpty()); } private static MultiValueMap getRefreshTokenRequestParameters(OAuth2Authorization authorization) { @@ -365,7 +365,9 @@ public class OAuth2RefreshTokenGrantTests { @EnableWebSecurity @Configuration(proxyBeanMethods = false) - static class AuthorizationServerConfigurationWithPublicClientAuthentication extends AuthorizationServerConfiguration { + static class AuthorizationServerConfigurationWithPublicClientAuthentication + extends AuthorizationServerConfiguration { + // @formatter:off @Bean SecurityFilterChain authorizationServerSecurityFilterChain( @@ -393,6 +395,7 @@ public class OAuth2RefreshTokenGrantTests { return http.build(); } // @formatter:on + } @Transient @@ -431,6 +434,7 @@ public class OAuth2RefreshTokenGrantTests { } private static final class PublicClientRefreshTokenAuthenticationProvider implements AuthenticationProvider { + private final RegisteredClientRepository registeredClientRepository; private PublicClientRefreshTokenAuthenticationProvider(RegisteredClientRepository registeredClientRepository) { @@ -440,8 +444,7 @@ public class OAuth2RefreshTokenGrantTests { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { - PublicClientRefreshTokenAuthenticationToken publicClientAuthentication = - (PublicClientRefreshTokenAuthenticationToken) authentication; + PublicClientRefreshTokenAuthenticationToken publicClientAuthentication = (PublicClientRefreshTokenAuthenticationToken) authentication; if (!ClientAuthenticationMethod.NONE.equals(publicClientAuthentication.getClientAuthenticationMethod())) { return null; @@ -453,8 +456,8 @@ public class OAuth2RefreshTokenGrantTests { throwInvalidClient(OAuth2ParameterNames.CLIENT_ID); } - if (!registeredClient.getClientAuthenticationMethods().contains( - publicClientAuthentication.getClientAuthenticationMethod())) { + if (!registeredClient.getClientAuthenticationMethods() + .contains(publicClientAuthentication.getClientAuthenticationMethod())) { throwInvalidClient("authentication_method"); } @@ -467,11 +470,8 @@ public class OAuth2RefreshTokenGrantTests { } private static void throwInvalidClient(String parameterName) { - OAuth2Error error = new OAuth2Error( - OAuth2ErrorCodes.INVALID_CLIENT, - "Public client authentication failed: " + parameterName, - null - ); + OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_CLIENT, + "Public client authentication failed: " + parameterName, null); throw new OAuth2AuthenticationException(error); } 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 fbee0131..6df29da2 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 @@ -683,7 +683,7 @@ public class OidcClientRegistrationTests { // @formatter:on private Consumer> configureClientRegistrationConverters() { - // @formatter:off + // @formatter:off return (authenticationProviders) -> authenticationProviders.forEach(authenticationProvider -> { List supportedCustomClientMetadata = List.of("custom-metadata-name-1", "custom-metadata-name-2"); @@ -769,9 +769,11 @@ public class OidcClientRegistrationTests { } - private static class CustomRegisteredClientConverter implements Converter { - private final OidcClientRegistrationRegisteredClientConverter delegate = - new OidcClientRegistrationRegisteredClientConverter(); + private static class CustomRegisteredClientConverter + implements Converter { + + private final OidcClientRegistrationRegisteredClientConverter delegate = new OidcClientRegistrationRegisteredClientConverter(); + private final List supportedCustomClientMetadata; private CustomRegisteredClientConverter(List supportedCustomClientMetadata) { @@ -783,7 +785,7 @@ public class OidcClientRegistrationTests { RegisteredClient registeredClient = this.delegate.convert(clientRegistration); ClientSettings.Builder clientSettingsBuilder = ClientSettings - .withSettings(registeredClient.getClientSettings().getSettings()); + .withSettings(registeredClient.getClientSettings().getSettings()); if (!CollectionUtils.isEmpty(this.supportedCustomClientMetadata)) { clientRegistration.getClaims().forEach((claim, value) -> { if (this.supportedCustomClientMetadata.contains(claim)) { @@ -797,9 +799,11 @@ public class OidcClientRegistrationTests { } - private static class CustomClientRegistrationConverter implements Converter { - private final RegisteredClientOidcClientRegistrationConverter delegate = - new RegisteredClientOidcClientRegistrationConverter(); + private static class CustomClientRegistrationConverter + implements Converter { + + private final RegisteredClientOidcClientRegistrationConverter delegate = new RegisteredClientOidcClientRegistrationConverter(); + private final List supportedCustomClientMetadata; private CustomClientRegistrationConverter(List supportedCustomClientMetadata) { @@ -822,6 +826,7 @@ public class OidcClientRegistrationTests { return OidcClientRegistration.withClaims(clientMetadata).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 1a0d7db0..5dc16c6d 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 @@ -472,81 +472,85 @@ public class OidcTests { // gh-1422 @Test - public void requestWhenAuthenticationRequestWithOfflineAccessScopeThenTokenResponseIncludesRefreshToken() throws Exception { + public void requestWhenAuthenticationRequestWithOfflineAccessScopeThenTokenResponseIncludesRefreshToken() + throws Exception { this.spring.register(AuthorizationServerConfigurationWithCustomRefreshTokenGenerator.class).autowire(); RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .scope(OidcScopes.OPENID) - .scope("offline_access") - .build(); + .scope(OidcScopes.OPENID) + .scope("offline_access") + .build(); this.registeredClientRepository.save(registeredClient); - MultiValueMap authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient); - MvcResult mvcResult = this.mvc.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI) - .queryParams(authorizationRequestParameters) - .with(user("user"))) - .andExpect(status().is3xxRedirection()) - .andReturn(); + MultiValueMap authorizationRequestParameters = getAuthorizationRequestParameters( + registeredClient); + MvcResult mvcResult = this.mvc + .perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters) + .with(user("user"))) + .andExpect(status().is3xxRedirection()) + .andReturn(); String redirectedUrl = mvcResult.getResponse().getRedirectedUrl(); String expectedRedirectUri = authorizationRequestParameters.getFirst(OAuth2ParameterNames.REDIRECT_URI); assertThat(redirectedUrl).matches(expectedRedirectUri + "\\?code=.{15,}&state=state"); String authorizationCode = extractParameterFromRedirectUri(redirectedUrl, "code"); - OAuth2Authorization authorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE); + OAuth2Authorization authorization = this.authorizationService.findByToken(authorizationCode, + AUTHORIZATION_CODE_TOKEN_TYPE); - this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) - .params(getTokenRequestParameters(registeredClient, authorization)) - .header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth( - registeredClient.getClientId(), registeredClient.getClientSecret()))) - .andExpect(status().isOk()) - .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) - .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) - .andExpect(jsonPath("$.access_token").isNotEmpty()) - .andExpect(jsonPath("$.token_type").isNotEmpty()) - .andExpect(jsonPath("$.expires_in").isNotEmpty()) - .andExpect(jsonPath("$.refresh_token").isNotEmpty()) - .andExpect(jsonPath("$.scope").isNotEmpty()) - .andExpect(jsonPath("$.id_token").isNotEmpty()) - .andReturn(); + this.mvc + .perform(post(DEFAULT_TOKEN_ENDPOINT_URI).params(getTokenRequestParameters(registeredClient, authorization)) + .header(HttpHeaders.AUTHORIZATION, + "Basic " + encodeBasicAuth(registeredClient.getClientId(), registeredClient.getClientSecret()))) + .andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) + .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) + .andExpect(jsonPath("$.access_token").isNotEmpty()) + .andExpect(jsonPath("$.token_type").isNotEmpty()) + .andExpect(jsonPath("$.expires_in").isNotEmpty()) + .andExpect(jsonPath("$.refresh_token").isNotEmpty()) + .andExpect(jsonPath("$.scope").isNotEmpty()) + .andExpect(jsonPath("$.id_token").isNotEmpty()) + .andReturn(); } // gh-1422 @Test - public void requestWhenAuthenticationRequestWithoutOfflineAccessScopeThenTokenResponseDoesNotIncludeRefreshToken() throws Exception { + public void requestWhenAuthenticationRequestWithoutOfflineAccessScopeThenTokenResponseDoesNotIncludeRefreshToken() + throws Exception { this.spring.register(AuthorizationServerConfigurationWithCustomRefreshTokenGenerator.class).autowire(); - RegisteredClient registeredClient = TestRegisteredClients.registeredClient() - .scope(OidcScopes.OPENID) - .build(); + RegisteredClient registeredClient = TestRegisteredClients.registeredClient().scope(OidcScopes.OPENID).build(); this.registeredClientRepository.save(registeredClient); - MultiValueMap authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient); - MvcResult mvcResult = this.mvc.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI) - .queryParams(authorizationRequestParameters) - .with(user("user"))) - .andExpect(status().is3xxRedirection()) - .andReturn(); + MultiValueMap authorizationRequestParameters = getAuthorizationRequestParameters( + registeredClient); + MvcResult mvcResult = this.mvc + .perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters) + .with(user("user"))) + .andExpect(status().is3xxRedirection()) + .andReturn(); String redirectedUrl = mvcResult.getResponse().getRedirectedUrl(); String expectedRedirectUri = authorizationRequestParameters.getFirst(OAuth2ParameterNames.REDIRECT_URI); assertThat(redirectedUrl).matches(expectedRedirectUri + "\\?code=.{15,}&state=state"); String authorizationCode = extractParameterFromRedirectUri(redirectedUrl, "code"); - OAuth2Authorization authorization = this.authorizationService.findByToken(authorizationCode, AUTHORIZATION_CODE_TOKEN_TYPE); + OAuth2Authorization authorization = this.authorizationService.findByToken(authorizationCode, + AUTHORIZATION_CODE_TOKEN_TYPE); - this.mvc.perform(post(DEFAULT_TOKEN_ENDPOINT_URI) - .params(getTokenRequestParameters(registeredClient, authorization)) - .header(HttpHeaders.AUTHORIZATION, "Basic " + encodeBasicAuth( - registeredClient.getClientId(), registeredClient.getClientSecret()))) - .andExpect(status().isOk()) - .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) - .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) - .andExpect(jsonPath("$.access_token").isNotEmpty()) - .andExpect(jsonPath("$.token_type").isNotEmpty()) - .andExpect(jsonPath("$.expires_in").isNotEmpty()) - .andExpect(jsonPath("$.refresh_token").doesNotExist()) - .andExpect(jsonPath("$.scope").isNotEmpty()) - .andExpect(jsonPath("$.id_token").isNotEmpty()) - .andReturn(); + this.mvc + .perform(post(DEFAULT_TOKEN_ENDPOINT_URI).params(getTokenRequestParameters(registeredClient, authorization)) + .header(HttpHeaders.AUTHORIZATION, + "Basic " + encodeBasicAuth(registeredClient.getClientId(), registeredClient.getClientSecret()))) + .andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.CACHE_CONTROL, containsString("no-store"))) + .andExpect(header().string(HttpHeaders.PRAGMA, containsString("no-cache"))) + .andExpect(jsonPath("$.access_token").isNotEmpty()) + .andExpect(jsonPath("$.token_type").isNotEmpty()) + .andExpect(jsonPath("$.expires_in").isNotEmpty()) + .andExpect(jsonPath("$.refresh_token").doesNotExist()) + .andExpect(jsonPath("$.scope").isNotEmpty()) + .andExpect(jsonPath("$.id_token").isNotEmpty()) + .andReturn(); } private static MultiValueMap getAuthorizationRequestParameters(RegisteredClient registeredClient) { @@ -728,7 +732,8 @@ public class OidcTests { @EnableWebSecurity @Configuration - static class AuthorizationServerConfigurationWithCustomRefreshTokenGenerator extends AuthorizationServerConfiguration { + static class AuthorizationServerConfigurationWithCustomRefreshTokenGenerator + extends AuthorizationServerConfiguration { // @formatter:off @Bean @@ -763,13 +768,14 @@ public class OidcTests { } private static final class CustomRefreshTokenGenerator implements OAuth2TokenGenerator { + private final OAuth2RefreshTokenGenerator delegate = new OAuth2RefreshTokenGenerator(); @Nullable @Override public OAuth2RefreshToken generate(OAuth2TokenContext context) { - if (context.getAuthorizedScopes().contains(OidcScopes.OPENID) && - !context.getAuthorizedScopes().contains("offline_access")) { + if (context.getAuthorizedScopes().contains(OidcScopes.OPENID) + && !context.getAuthorizedScopes().contains("offline_access")) { return null; } return this.delegate.generate(context); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientConfigurationAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientConfigurationAuthenticationProviderTests.java index 7d70a9de..595435e0 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientConfigurationAuthenticationProviderTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientConfigurationAuthenticationProviderTests.java @@ -119,8 +119,8 @@ public class OidcClientConfigurationAuthenticationProviderTests { @Test public void setClientRegistrationConverterWhenNullThenThrowIllegalArgumentException() { assertThatIllegalArgumentException() - .isThrownBy(() -> this.authenticationProvider.setClientRegistrationConverter(null)) - .withMessage("clientRegistrationConverter cannot be null"); + .isThrownBy(() -> this.authenticationProvider.setClientRegistrationConverter(null)) + .withMessage("clientRegistrationConverter cannot be null"); } @Test diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProviderTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProviderTests.java index 8124f01b..9e4093b3 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProviderTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProviderTests.java @@ -172,8 +172,8 @@ public class OidcClientRegistrationAuthenticationProviderTests { @Test public void setClientRegistrationConverterWhenNullThenThrowIllegalArgumentException() { assertThatIllegalArgumentException() - .isThrownBy(() -> this.authenticationProvider.setClientRegistrationConverter(null)) - .withMessage("clientRegistrationConverter cannot be null"); + .isThrownBy(() -> this.authenticationProvider.setClientRegistrationConverter(null)) + .withMessage("clientRegistrationConverter cannot be null"); } @Test 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 96ed9f9b..d8ccb1ea 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 @@ -131,11 +131,16 @@ 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\"]"); - 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\"]"); - 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\"]"); + assertThat(providerConfigurationResponse).contains( + "\"grant_types_supported\":[\"authorization_code\",\"client_credentials\",\"refresh_token\",\"urn:ietf:params:oauth:grant-type:device_code\"]"); + 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\"]"); + 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\"]"); assertThat(providerConfigurationResponse).contains("\"code_challenge_methods_supported\":[\"S256\"]"); assertThat(providerConfigurationResponse).contains("\"subject_types_supported\":[\"public\"]"); assertThat(providerConfigurationResponse).contains("\"id_token_signing_alg_values_supported\":[\"RS256\"]"); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ErrorAuthenticationFailureHandlerTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ErrorAuthenticationFailureHandlerTests.java index 1dbfdfba..6b5863c7 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ErrorAuthenticationFailureHandlerTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2ErrorAuthenticationFailureHandlerTests.java @@ -39,6 +39,7 @@ import static org.mockito.Mockito.verifyNoInteractions; * @author Dmitriy Dubson */ public class OAuth2ErrorAuthenticationFailureHandlerTests { + private final OAuth2ErrorAuthenticationFailureHandler authenticationFailureHandler = new OAuth2ErrorAuthenticationFailureHandler(); @Test